Sticky headers and sidebars

position: sticky

Baseline widely available
  • Chrome56
  • Edge16
  • Firefox59
  • Safari13

Features it needs

These libraries measured scroll position and toggled position: fixed with a computed offset. position: sticky does it in the compositor, so it does not jitter and does not run code on scroll. Two things trip people up: sticky is relative to the nearest scrolling ancestor, so an overflow: hidden or overflow: auto anywhere up the tree silently breaks it, and you must set at least one of top, right, bottom or left.

When this applies

A header, sidebar or table head should stick while its container scrolls.

The native approach

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
}

/* A sidebar that sticks until its section scrolls past. */
.sidebar {
  position: sticky;
  top: 5rem;
  align-self: start;
}

MDN reference

When the dependency is still right

An answer that always says "the platform covers it" is worse than no answer. These are the cases where this one does not hold.

  • You need to know when the element became stuck, to add a shadow or shrink it. Nothing in CSS exposes that state directly, so this still wants an IntersectionObserver sentinel.
  • You need the element to stick relative to the viewport while its parent has overflow set. Sticky is scoped to the nearest scroll container, so this needs a different structure.
  • You need it to stop sticking at a computed point unrelated to its containing block.

Building it

This catalog stops at the swap. These guides go through the implementation and the fallbacks. They come from Google Chrome's modern-web-guidance, Apache-2.0.

Packages this covers