No Login Data Private Local Save

scroll‑state Container Query Demo - Online Test stuck/snapped

5
0
0
0

Scroll‑State Container Query Tester

Live demo & compatibility test for CSS @container scroll-state() — detect stuck & snapped elements

Container Queries Level 2
Detecting browser support for container-type: scroll-state

Sticky Detection

not stuck
0px

Scroll down — when a sticky header gets stuck at top, the @container scroll-state(stuck: top) query activates.

This section introduces the concept of scroll-state container queries. The header above uses position: sticky; top: 0;.

When you scroll this container, the header will stick to the top edge. The container has container-type: scroll-state enabled.

The CSS @container scroll-state(stuck: top) rule detects this sticky state and applies highlight styles automatically — no JavaScript required (in supported browsers).

The scroll-state container query observes the scrollport for sticky-positioned descendants. When any position: sticky element becomes physically stuck to the specified edge, the query matches.

This is a boolean state query — it's either true or false. You can combine it with other container queries using and / or logic.

Key insight: the query fires for any sticky child inside the container, not just a specific one.

Imagine a table of contents sidebar: when a sticky header is active, you could dim non-relevant items or highlight the current section.

Another use case: sticky table headers that change appearance when "locked" — adding a shadow, changing background, or revealing action buttons.

Scroll-state queries bring these interactions to CSS, eliminating the need for complex IntersectionObserver setups.

As of late 2024, scroll-state container queries are available in Chrome Canary behind the Experimental Web Platform Features flag.

Safari and Firefox are actively working on implementation. This tool helps you test whether your current browser supports the feature natively.

For production, always provide a JavaScript fallback using IntersectionObserver or scroll event listeners.

Scroll-state container queries unlock new possibilities for state-driven styling without JavaScript. Combined with size container queries, they form a powerful responsive design toolkit.

Try the snap demo in the next column, and check the FAQ below for deeper insights.

Snap Detection

not snapped
0px

Scroll to snap cards into place — @container scroll-state(snapped: block) detects when a child is aligned.

🔵
Card One
Snap point #1
🟢
Card Two
Snap point #2
🟣
Card Three
Snap point #3
🟠
Card Four
Snap point #4
🔴
Card Five
Snap point #5

CSS Code Preview

scroll-state

Sticky Detection

@container sticky-demo scroll-state(stuck: top) { .sticky-header { background: #4f6ef7; color: white; box-shadow: 0 4px 16px rgba(79,110,247,0.3); } .status-dot { background: #22c55e; } }

Snap Detection

@container snap-demo scroll-state(snapped: block) { .snap-item { background: #eef2ff; border-color: #c7d2fe; } .snap-item .snap-icon { transform: scale(1.15); color: #4f6ef7; } }

Container Declaration

.scroll-container-sticky { container-type: scroll-state; container-name: sticky-demo; overflow-y: auto; } .scroll-container-snap { container-type: scroll-state; container-name: snap-demo; overflow-y: scroll; scroll-snap-type: y mandatory; }

Frequently Asked Questions

What exactly is a scroll-state container query?
A scroll-state container query is a CSS feature that lets you style elements based on the scroll state of a container — specifically whether a sticky element is currently "stuck" to an edge, or whether a scroll-snap child is currently snapped into alignment. It extends the Container Queries specification (Level 2) with the scroll-state container type. This enables purely CSS-driven reactions to scroll interactions without JavaScript.
Which browsers support scroll-state container queries?
As of early 2025, scroll-state container queries are an experimental feature. They are available in Chrome 131+ when the chrome://flags/#enable-experimental-web-platform-features flag is enabled. Safari and Firefox have expressed interest and are tracking the specification, but native support is not yet available in stable releases. Use @supports (container-type: scroll-state) for feature detection.
What's the difference between stuck: top and stuck: block-start?
stuck: top refers to the physical top edge regardless of writing mode. stuck: block-start is logical — it refers to the block-start edge, which depends on the writing mode (top in horizontal-tb, right in vertical-rl). For most English-language sites, they behave identically. Using logical properties (block-start, block-end, inline-start, inline-end) makes your styles more portable across different writing modes.
Can I detect multiple sticky elements at once?
Yes! The scroll-state(stuck: top) query matches if any sticky-positioned descendant inside the container is currently stuck to the top edge. You don't need to target a specific element — the query acts as a global state flag for the entire scroll container. This makes it perfect for patterns like "is any section header currently pinned?" to adjust a table of contents or toolbar.
How does snapped detection work with scroll-snap?
scroll-state(snapped: block) detects whether the container's scroll position is currently aligned to a snap point in the block direction. For scroll-snap-type: y mandatory, the scroll position will always snap (so the query may always match once scrolling stops). For proximity snapping, the query only matches when close enough to a snap point. You can query snapped: x, snapped: y, snapped: block, snapped: inline, or snapped: both.
What's a good JavaScript fallback for production?
For sticky detection, use IntersectionObserver with a rootMargin that matches the sticky offset, or compare the sticky element's getBoundingClientRect().top against its container's top. For snap detection, listen to the scrollend event and check if scrollTop aligns with any child's offsetTop. Apply CSS classes (.is-stuck, .is-snapped) to replicate the container query behavior. This demo uses exactly this fallback approach for browsers without native support.
Can I combine scroll-state queries with size queries?
Yes, you can declare both container-type: scroll-state size; (or use separate container names) to query both scroll state and dimensions. However, note that container-type: scroll-state alone does not enable size queries — you need to explicitly include size or inline-size. You can also nest containers: an outer container tracks size, while an inner one tracks scroll-state, giving you fine-grained control.

Key Concepts & Quick Reference

Query Type Syntax Detects Requires
stuck: top @container scroll-state(stuck: top) Sticky element pinned to top edge position: sticky; top: 0; on child
stuck: bottom @container scroll-state(stuck: bottom) Sticky element pinned to bottom edge position: sticky; bottom: 0; on child
stuck: left / right @container scroll-state(stuck: left) Sticky element pinned horizontally position: sticky; left: 0; on child + horizontal scroll
snapped: block @container scroll-state(snapped: block) Child aligned to block-axis snap point scroll-snap-type on container + scroll-snap-align on children
snapped: inline @container scroll-state(snapped: inline) Child aligned to inline-axis snap point Horizontal scroll-snap-type
snapped: both @container scroll-state(snapped: both) Child aligned in both axes simultaneously 2D scroll-snap-type