← Back

CSS Scroll State Queries

CSS Scroll State Container Queries let you style elements based on their scroll-related state—whether they're stuck, snapped, or scrollable—directly from CSS, no JavaScript required.

Read more on MDN →

Experimental Feature: CSS Scroll State Queries require Chrome 133+. This demo uses @supports for progressive enhancement.

/* Define scroll-state container */
.container {
  container-type: scroll-state;
}

/* Query stuck, snapped, or scrollable states */
@container scroll-state(stuck: top) { /* styles */ }
@container scroll-state(snapped: x) { /* styles */ }
@container scroll-state(scrollable: bottom) { /* styles */ }

Stuck State

Query when a sticky element is stuck to an edge. Perfect for adding shadows or visual feedback to sticky headers.

.sticky-container {
  container-type: scroll-state;
}

.sticky-header {
  position: sticky;
  top: 0;
}

@container scroll-state(stuck: top) {
  .header-content {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    background: hsl(var(--card));
  }
}

Scroll within the container to see the navbar background appear when stuck

scroll-state(stuck: top)

Content block 1
Content block 2
Content block 3
Content block 4
Content block 5
Content block 6
Content block 7
Content block 8

Triggers instantly when stuck

scroll-driven animation

Content block 1
Content block 2
Content block 3
Content block 4
Content block 5
Content block 6
Content block 7
Content block 8

Animates over 0-50px scroll distance

Snapped State

Query when a scroll-snap item is snapped to its alignment point. Great for highlighting the active item in carousels.

.carousel {
  scroll-snap-type: x mandatory;
}

.carousel-item {
  container-type: scroll-state;
  scroll-snap-align: center;
}

@container scroll-state(snapped: x) {
  .card {
    opacity: 1;
    transform: scale(1);
  }
}

Scroll horizontally to snap between cards—the snapped card will be highlighted

Scrollable State

Query when a container has scrollable overflow in a direction. Use it to show scroll shadows or hide scroll-to-top buttons when not needed.

.scroll-container {
  container-type: scroll-state;
}

@container scroll-state(scrollable: top) {
  .shadow-top { opacity: 1; }
  .scroll-to-top { opacity: 1; }
}

@container scroll-state(scrollable: bottom) {
  .shadow-bottom { opacity: 1; }
}

Add or remove content to see the scroll shadows and scroll-to-top button appear

Scroll down to see the top shadow appear
The shadows indicate scrollable content
Top shadow = content above viewport

© 2026 rege. All rights reserved.