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();