Color Mode

CSS Scroll Snap

Scroll snap lets a scroll container rest at predictable positions after a user scrolls or swipes. You can build horizontal card strips, image carousels, and full-height section paging without JavaScript timers or wheel hijacking, using only CSS on the scroll container and its children.

This learning activity explains the core properties, the difference between mandatory and proximity snapping, and how to combine snap with accessible scrolling habits. For a concise overview from the Chrome team, see Well-controlled scrolling with CSS Scroll Snap (web.dev).

How Scroll Snap Works

You declare two roles:

  1. Scroll container (often with overflow: auto or scroll): set scroll-snap-type to define the axis and strictness.
  2. Snap targets (children): set scroll-snap-align (and optionally scroll-snap-stop, scroll-margin) so the browser knows where to align each item when scrolling stops.

        .carousel {
            display: flex;
            gap: 1rem;
            overflow-x: auto;
            scroll-snap-type: x mandatory;
            scroll-padding-inline: 1rem;
        }

        .carousel__slide {
            flex: 0 0 80%;
            scroll-snap-align: start;
            scroll-snap-stop: always;
        }
    

scroll-snap-type

Applied to the scroll container. Syntax (simplified):


        scroll-snap-type: none;
        scroll-snap-type: x | y | block | inline | both;
        /* Often combined with mandatory | proximity */
        scroll-snap-type: x mandatory;
        scroll-snap-type: y proximity;
    
Overflow required

The element must actually scroll: set explicit dimensions or constrain content so overflow creates a scrollport. Flex and grid children often need min-width: 0 (or min-height) so they can shrink and allow overflow.

scroll-snap-align

Applied to snap children. Common values: start, center, end. The browser aligns the snap area of each child to the snapport of the container when scrolling stops.

scroll-snap-stop

Lets you force the user to stop at each item on the way (useful for full-bleed slides):


        .slide {
            scroll-snap-align: center;
            scroll-snap-stop: always;
        }
    

Without this, fast flings may skip across multiple snap points.

scroll-padding and scroll-margin

scroll-padding-* on the container insets the snapport (for example, to keep slides clear of a fixed header or edge gutters).

scroll-margin-* on children adjusts where each item’s snap position sits, similar to how margin affects layout but for snapping.

Demo: Horizontal Card Strip

Drag the scrollbar or swipe on a trackpad. Each card snaps to the start of the scrollport.

Card one
Card two
Card three
Card four

        .track {
            display: flex;
            gap: 0.75rem;
            overflow-x: auto;
            scroll-snap-type: x mandatory;
        }

        .card {
            flex: 0 0 70%;
            scroll-snap-align: start;
        }
    

Demo: Vertical Section Snapping

Full-height sections with scroll-snap-type: y mandatory create a “page at a time” feel. Use sparingly on long-form reading pages; it fits marketing landings and slideshow-style layouts.

Section A
Section B
Section C

Accessibility and UX

Scroll snap is a layout aid, not a replacement for accessible carousel semantics. Complex widgets may still need appropriate ARIA roles and keyboard interaction patterns.

Debugging Tips

Summary

Use scroll-snap-type on the scroller and scroll-snap-align on items; tune with scroll-padding, scroll-margin, and scroll-snap-stop. Prefer proximity when rigid snapping feels heavy, and always consider keyboard users and motion preferences when snap affects navigation.