For years, styling web elements based on their dynamic scrolling position—such as adding a drop-shadow to a header when it becomes stuck, or highlighting active navigation items—required continuous JavaScript scroll listeners (window.addEventListener('scroll')) or IntersectionObserver triggers. These JavaScript approaches frequently introduce main-thread layout thrashing and jitter during rapid touch scrolling on iOS. CSS Container Queries Scroll-State introduces a declarative, GPU-accelerated mechanism to apply styles dynamically based on whether an element is stuck, snapped, or overflowing. Safari Web Inspector provides specialized inspection tools to debug scroll-state container queries.
Understanding @container scroll-state Syntax
Scroll-state container queries evaluate the physical scrolling status of an established container context using the container-type: scroll-state property:
scroll-state(stuck: top): Evaluates to true when aposition: stickyelement pins against the top edge of the scroll container.scroll-state(snapped: inline): Triggers when an element aligns with a defined scroll-snap point in a horizontal carousel.scroll-state(overflowing: bottom): Triggers when container content overflows the bottom viewport edge, enabling dynamic scroll affordance indicators without JavaScript.
Configuring a Self-Styling Sticky Navigation Bar
Author clean declarative CSS that automatically adds borders and background elevation when a header sticks:
/* Define scroll-state container */
.sticky-wrapper {
container-type: scroll-state;
position: sticky;
top: 0;
z-index: 100;
}
/* Child component adapting to stuck state */
.navigation-bar {
display: flex;
align-items: center;
padding: 1rem 1.5rem;
background-color: transparent;
transition: background-color 0.2s ease, box-shadow 0.2s ease;
}
/* Query active stuck state */
@container scroll-state(stuck: top) {
.navigation-bar {
background-color: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(8px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
}
Inspecting Scroll-State Queries in Safari Web Inspector
To inspect and audit scroll-state queries live using Safari Web Inspector on macOS:
- Open Safari and navigate to the web page.
- Right-click the sticky header element and select Inspect Element.
- In the Elements panel, look at the DOM tree node. Safari displays a container badge next to elements with
container-type: scroll-state. - In the Styles sidebar, locate the
@container scroll-state(stuck: top)rule block. - Scroll the web page in the browser window. Observe that as soon as the element pins to the top edge, Safari dynamically illuminates the container query block in the Styles sidebar, proving that the state is actively evaluated.
- Select the Computed panel to verify that active background and shadow values reflect the stuck styles.
Validating iOS Momentum and Inertial Scrolling
To ensure scroll-state transitions trigger smoothly during high-velocity gestures:
- Connect your iPhone to your Mac via USB and inspect the live Safari tab under the Develop menu.
- Fling the screen rapidly to test inertial deceleration. Confirm that scroll-state styles engage instantly without visual lag or missing frame drops.