CSSTIL

Style sticky elements when they are stuck


It is now possible to detect whether or not a position: sticky element is currently “stuck” using only CSS. 🤩

Meet Container Scroll State Queries

Container Scroll State Queries enable CSS to query the state of an element in regards to its scroll behaviour:

  • Is an element scrollable? If so, in which direction is it scrollable? (use scrollable:)
  • Is a scroll-snapping element currently snapped? (use snapped:)
  • Is a sticky element currently stuck? (use stuck: )

This feature is one type of container queries. To enable querying for scroll state, setup a container using container-type: scroll-state; with an optional container-name on the element you want to query.

In a @container query, you can then check for the scroll state of the container element and apply conditional styling to it descenants:

@container my-container-name scroll-state(stuck: top) {
  .inner-element {
    color: red;
  }
}

Demo

See the Pen Detect Sticky State with only CSS by Martin Grubinger (@mgrubinger) on CodePen.

Use case

One use case I came across this recently is on the npmx.dev package page. When you scroll down a bit, the package name stays on top (due to position: sticky) and, to visualize the boundaries between elements, they add a border to the bottom of the package name element. It seems they use JavaScript to achieve that (probably using Intersection Observer, but I haven’t checked), but this would be a perfect use case for a scroll-state container query.

Browser Support

Currently, only Chromium-based browsers (118+) support this feature. See Container scroll-state queries on Can I Use.