fix(stickyHeader): 🐛 add a placeholder element to page header to avoid layout shift when stickied

Closes: #854
This commit is contained in:
alistair3149 2024-07-07 17:58:02 -04:00
parent e9fd488cee
commit e5336c4610
No known key found for this signature in database
3 changed files with 37 additions and 7 deletions

View file

@ -39,17 +39,41 @@ function init() {
return;
}
const toggleStickyClass = ( state ) => () => {
const placeholder = document.createElement( 'div' );
placeholder.id = 'citizen-page-header-sticky-placeholder';
header.insertAdjacentElement( 'afterend', placeholder );
let staticHeaderHeight = header.offsetHeight;
const toggleStickyHeader = ( isSticky ) => {
window.requestAnimationFrame( () => {
document.body.classList.toggle( STICKY_CLASS, state );
document.body.classList.toggle( STICKY_CLASS, isSticky );
placeholder.style.height = `${ staticHeaderHeight - header.offsetHeight }px`;
} );
};
const observer = initIntersectionObserver(
toggleStickyClass( true ),
toggleStickyClass( false )
() => {
toggleStickyHeader( true );
},
() => {
toggleStickyHeader( false );
}
);
observer.observe( sentinel );
const onResize = () => {
toggleStickyHeader( false );
};
const onResizeEnd = () => {
// Refresh static header height after resize
staticHeaderHeight = header.offsetHeight;
toggleStickyHeader( true );
};
window.addEventListener( 'resize', onResize );
window.addEventListener( 'resize', mw.util.debounce( onResizeEnd, 250 ) );
}
module.exports = {

View file

@ -1,10 +1,14 @@
#citizen-page-header-sticky-sentinel {
grid-area: content; // align right above content
grid-area: afterHeader; // align right above content
height: 1px;
visibility: hidden;
contain: strict;
}
#citizen-page-header-sticky-placeholder {
grid-area: afterHeader;
}
.ve-activated,
.action-edit {
// HACK: So sticky header will never trigger in edit action

View file

@ -13,7 +13,8 @@
.citizen-body-container {
display: grid;
grid-template-areas:
'header'
'header'
'afterHeader'
'content'
'footer';
// Using auto as min value will cause overflow
@ -59,7 +60,8 @@
.citizen-toc-enabled {
.citizen-body-container {
grid-template-areas:
'header header'
'header header'
'afterHeader afterHeader'
'content sidebar'
'footer footer';
grid-template-columns: minmax( 0, var( --width-layout ) ) var( --width-toc );