AZ.dev

Why position sticky isn't sticking

| browsers: all modern

A sticky element needs an inset and a scrolling ancestor with no overflow other than visible in between. Check those two things first.

header {
  position: sticky;
  top: 0;
}

The three usual causes

  1. No inset. Without top, bottom, left or right, sticky behaves like relative. top: 0 is the one you mean for a header.

  2. An ancestor with overflow. Any element between the sticky one and the scroller with overflow: hidden, auto, scroll or clip becomes the scroll container it sticks within. If that ancestor doesn’t scroll itself, the element never moves. Find it with:

    let el = document.querySelector("header").parentElement;
    while (el) {
      const o = getComputedStyle(el).overflow;
      if (o !== "visible") console.log(el, o);
      el = el.parentElement;
    }
    

    Commonly it’s an overflow-x: hidden on body or a wrapper added to stop horizontal scroll. Since overflow-x: hidden forces overflow-y to auto, that wrapper is now the scroller. Move the rule to the element that actually overflows, or use overflow-x: clip, which doesn’t create a scroll container.

  3. The parent is exactly as tall as the element. Sticky sticks within its parent’s box. A header that is its parent’s only child has nowhere to travel. Give it siblings or move it up a level.

Gotchas

sticky position overflow scroll header

This entry is one card on a printable cheat sheet:

CSS & Layout Essentials Cheat Sheet

Was this helpful?

Related Entries

Responsive grid columns with auto-fit or auto-fillStop a flex or grid child from overflowing its container