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.