sticky header w/o anim
https://twitter.com/jaffathecake/status/1547884638227509248
by phloe
HTML
<div class="header-container-container">
<div class="header-container">
<div class="header">Header</div>
</div>
</div>
<p>First paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
<p>Paragraph</p>
CSS
body {
margin: 0;
}
.header {
position: sticky;
top: 0;
background: blue;
color: white;
padding: 20px;
pointer-events: auto;
height: 20px;
}
.header-container {
position: absolute;
top: 0;
width: 100%;
pointer-events: none;
}
.header-container-container {
position: relative;
height: 60px;
}
JavaScript
const header = document.querySelector('.header');
const headerContainer = document.querySelector('.header-container');
const headerContainerContainer = document.querySelector('.header-container-container');
function fixHeaderoffset() {
const bounds = header.getBoundingClientRect();
// Avoid picking up overscroll
const scrollOffset = Math.min(
document.documentElement.scrollTop,
document.documentElement.offsetHeight - window.innerHeight
);
// The header is out of view.
// Change its container so it's just out of view.
if (bounds.top + bounds.height <= 0) {
headerContainer.style.height = scrollOffset + 'px';
headerContainer.style.marginBottom = bounds.height + (scrollOffset * -1) + 'px';
headerContainerContainer.style.height = bounds.height + 'px';
return;
}
// The header is fully in view.
// Change its container so this is the maximum y it can be.
if (bounds.top === 0) {
headerContainer.style.height = scrollOffset + bounds.height + 'px';
headerContainer.style.marginBottom = scrollOffset * -1 + 'px';
headerContainerContainer.style.height = bounds.height + 'px';
return;
}
// Otherwise, the header is partially visible, so do nothing.
}
addEventListener('scroll', () => fixHeaderoffset());
addEventListener('resize', () => fixHeaderoffset());
fixHeaderoffset();