CSS Scroll Snap Reference

scroll-snap-type, scroll-snap-align, scroll-margin properties with container/item split.

Reference for the CSS Scroll Snap module: container properties (scroll-snap-type, scroll-padding), item properties (scroll-snap-align, scroll-snap-stop, scroll-margin) and mandatory vs proximity behaviour. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What is the difference between mandatory and proximity?

scroll-snap-type: x mandatory forces the scroll to always rest on a snap point — you cannot stop between items. proximity only snaps when you release the scroll near a snap point, otherwise it stays put. Mandatory is ideal for full-screen carousels; proximity for long lists where free scrolling matters.

What CSS Scroll Snap does

Scroll Snap lets a scroll container rest on defined snap points instead of stopping anywhere. It powers carousels, paginated galleries and full-screen sections with no JavaScript. The properties split cleanly: a few go on the scroll container to define the axis and strictness, and the rest go on each scrollable item to define where it aligns. This reference lists them all with their accepted values.

How it works

The container declares an axis and strictness with scroll-snap-type; each child declares where it rests with scroll-snap-align:

.carousel {
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 1rem;
}
.carousel > .slide {
  scroll-snap-align: start;
  scroll-snap-stop: always;
  scroll-margin-left: 0.5rem;
}

mandatory guarantees the scroll always lands on a slide; proximity only snaps when you release near one. scroll-snap-align: start aligns each slide’s left edge to the (padded) container edge. scroll-snap-stop: always blocks a single fling from skipping past slides.

A full-page horizontal carousel with centered snapping and a sticky header clearance:

/* Scroll container */
.carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline-start: 1rem; /* clears any inset from the container edge */
  -webkit-overflow-scrolling: touch;  /* momentum on iOS */
}

/* Each slide */
.slide {
  flex: 0 0 100%;          /* full-width slide */
  scroll-snap-align: start;
  scroll-snap-stop: always; /* no swipe-skipping */
}

For centred cards where you want partial peek of adjacent cards:

.carousel { scroll-padding-inline: 10%; }
.card {
  flex: 0 0 80%;
  scroll-snap-align: center;
}

The 10% padding insets the snap boundary so the card centers with 10% of adjacent cards peeking in from each side.

Clearing a sticky header with scroll-padding

If your page has a fixed header (for example, 60 px tall), scroll targets can snap underneath it. scroll-padding-block-start insets the container’s snap area so items stop below the header:

.page {
  overflow-y: auto;
  scroll-snap-type: y proximity;
  scroll-padding-block-start: 60px;
}
.section {
  scroll-snap-align: start;
}

scroll-margin on an individual item achieves the same offset for that item only, without affecting all snapping.

mandatory vs proximity

mandatory is the stricter mode: the user cannot release the scroll between snap points — it always jumps to the nearest. This works well for full-screen sections or single-item carousels where landing between items would leave a broken-looking partial view.

proximity only snaps when the user releases near a snap point. Scrolling quickly past several items works normally, and the scroll only locks when the user slows and stops near a boundary. Prefer proximity for long scrollable lists where free scrolling is more important than precision.

Tips and notes

  • A snap container must actually scroll — set overflow and a constrained size, or nothing snaps.
  • Combine scroll-padding (container) with scroll-margin (item) to clear a sticky header.
  • Use logical-axis values block/inline for writing-mode-aware snapping.
  • scroll-snap-align: none opts a single item out of snapping inside a snapping container.
  • mandatory on a long page where items are taller than the viewport can trap users — proximity is safer in that case.