Sticky Header

A container-type: scroll-state demo — detects when a sticky header is "stuck" using native CSS where supported, falling back to IntersectionObserver everywhere else.

  • CSS
  • Vanilla JS
Checking…

container-type: scroll-state

Native CSS where supported, IntersectionObserver fallback everywhere else — the badge above tells you which path your browser is taking.

↓ Scroll down to see the header shrink

The CSS

/* shared "stuck" styles — used by both paths */
header.stuck .logo { font-size: 1rem; }

/* PATH A — native CSS (Chrome 133+) */
@supports (container-type: scroll-state) {
  header { container-type: scroll-state; }

  @container scroll-state(stuck: top) {
    .logo { font-size: 1rem; }
  }
}

/* PATH B — JS fallback (everything else) */
/* CSS.supports() check → IntersectionObserver adds .stuck */
const native = CSS.supports('container-type', 'scroll-state');

if (!native) {
  const observer = new IntersectionObserver(
    ([entry]) => header.classList.toggle('stuck', !entry.isIntersecting)
  );
  observer.observe(sentinel); /* 1px div above the header */
}
🎯

Zero JavaScript

Previously you'd need an IntersectionObserver or scroll listener just to know if a sticky header was "stuck". Now CSS handles it.

Native performance

Because it's driven by the browser's layout engine, there's no JS thread overhead or paint jank — transitions run on the compositor.

📐

Container query syntax

It uses the same @container at-rule you already know, extended with scroll-state queries instead of size queries.

🔧

Other states

Beyond stuck: top you can also query stuck: bottom, stuck: left, stuck: right, and overflowing snap containers.

🗺️

Browser support

Chrome 133+ ships it. Firefox and Safari are still behind a flag or not yet implemented — check caniuse for the latest.

🧩

Combine with size queries

A single element can expose both container-type: size scroll-state so you can mix size and scroll-state conditions in one rule.

🎨

Animate anything

Not just font sizes — transition colours, padding, opacity, transforms, or even grid layouts when the sticky state changes.

📜

Spec background

Part of CSS Containment Level 3. The scroll-state() function is the query mechanism; stuck is the first supported feature.

🚀

Keep scrolling

This page has enough cards to let you see the header fully transition. Scroll back to the top and watch it expand again.