scroll-snap-stop
Control whether a directional scroll can pass over an item’s snap position.
Overview
| Class | Declarations |
|---|---|
snap-always | scroll-snap-stop: always;
|
snap-normal | scroll-snap-stop: normal;
|
scroll-snap-stop:<value> | scroll-snap-stop: <value>;
|
Examples
Force a snap stop
snap-always prevents a directional scroll from passing over the item’s snap position. This track marks every card as a stop. Use Advance to send the same relative scroll request used in the following examples.
<div id="scrollport" class="flex overflow-x:auto gap-md scroll-snap-type:x|mandatory" tabindex="0" aria-label="Horizontal panels"> <article id="panel-1" class="flex-shrink:0 h:9rem w:12rem snap-always snap-start">Panel 1</article> <article id="panel-2" class="flex-shrink:0 h:9rem w:12rem snap-always snap-start">Panel 2</article> <article id="panel-3" class="flex-shrink:0 h:9rem w:12rem snap-always snap-start">Panel 3</article> <article id="panel-4" class="flex-shrink:0 h:9rem w:12rem snap-always snap-start">Panel 4</article> <article id="panel-5" class="flex-shrink:0 h:9rem w:12rem snap-always snap-start">Panel 5</article> <article id="panel-6" class="flex-shrink:0 h:9rem w:12rem snap-always snap-start">Panel 6</article></div>Generated CSS
@layer utilities { .snap-always { scroll-snap-stop: always }}The preview’s Advance control uses a single, immediate native relative scroll request:
document.querySelector('#scrollport').scrollBy({ left: 600, behavior: 'instant' })scroll-snap-stop does not restrict navigation that specifies only an endpoint, such as a fragment link or dragging the scrollbar to a new position.
This comparison uses immediate scrolling. Safari has a known issue with snapping during scripted smooth scrolling. Use native gestures when checking momentum on your target device.
Keep normal scroll momentum
snap-normal allows a directional scroll to pass over a snap point. Advance uses the same distance as the always example, so the browser can settle on a later card. Near the track’s end, the available scroll range limits the destination.
<div id="scrollport" class="flex overflow-x:auto gap-md scroll-snap-type:x|mandatory" tabindex="0" aria-label="Horizontal panels"> <article id="panel-1" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start">Panel 1</article> <article id="panel-2" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start">Panel 2</article> <article id="panel-3" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start">Panel 3</article> <article id="panel-4" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start">Panel 4</article> <article id="panel-5" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start">Panel 5</article> <article id="panel-6" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start">Panel 6</article></div>Use sparingly
Apply snap-always only where an intermediate stop helps orientation. Here Panel 2 is the deliberate stop, while the other cards allow pass-through. Snapping cannot guarantee that content is read and should not enforce a required workflow.
<div id="scrollport" class="flex overflow-x:auto gap-md scroll-snap-type:x|mandatory" tabindex="0" aria-label="Horizontal panels"> <article id="panel-1" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start">Panel 1</article> <article id="panel-2" class="flex-shrink:0 h:9rem w:12rem snap-always snap-start">Panel 2</article> <article id="panel-3" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start">Panel 3</article> <article id="panel-4" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start">Panel 4</article> <article id="panel-5" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start">Panel 5</article> <article id="panel-6" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start">Panel 6</article></div>Apply conditionally
Use selectors and conditional queries to apply the change only when its condition matches. The track permits passing snap positions by default and requires intermediate stops from sm. Reset after resizing, then use Advance again.
<div id="scrollport" class="flex overflow-x:auto gap-md scroll-snap-type:x|mandatory" tabindex="0" aria-label="Horizontal panels"> <article id="panel-1" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start snap-always@sm">Panel 1</article> <article id="panel-2" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start snap-always@sm">Panel 2</article> <article id="panel-3" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start snap-always@sm">Panel 3</article> <article id="panel-4" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start snap-always@sm">Panel 4</article> <article id="panel-5" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start snap-always@sm">Panel 5</article> <article id="panel-6" class="flex-shrink:0 h:9rem w:12rem snap-normal snap-start snap-always@sm">Panel 6</article></div>