CSS scroll-snap-type Property

This property defines how strictly snap points are enforced on a scroll container and which axis the snapping occurs on.

selector { scroll-snap-type: [ none | [ x | y | block | inline | both ] [ mandatory | proximity ]? ]; }
none Disables snapping behavior on the scroll container entirely.
x Enables scroll snapping along the horizontal axis only.
y Enables scroll snapping along the vertical axis only.
block Enables scroll snapping along the axis perpendicular to the flow of text.
inline Enables scroll snapping along the axis parallel to the flow of text.
both Enables scroll snapping on both the horizontal and vertical axes independently.
mandatory Forces the container to snap to a snap point whenever the user stops scrolling.
proximity Only snaps the container to a snap point if the scroll position is very close to one.

Code Examples

A basic horizontal image-style gallery where each item snaps to the center of the container as you scroll.

<style>
.gallery {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  width: 300px;
  border: 2px solid #333333;
}
.item {
  flex: 0 0 300px;
  height: 200px;
  scroll-snap-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  color: #ffffff;
}
.item:nth-child(odd) { background: #ff5733; }
.item:nth-child(even) { background: #3357ff; }
</style>
<div class="gallery">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
</div>

An advanced vertical full-page scroller that uses JavaScript to demonstrate how to dynamically disable snapping via the style object.

<style>
.slides-container {
  height: 100vh;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
}
.slide {
  height: 100vh;
  scroll-snap-align: start;
  padding: 50px;
  box-sizing: border-box;
}
#slide1 { background: #e1e1e1; }
#slide2 { background: #d2d2d2; }
</style>
<div class="slides-container" id="scroller">
  <section class="slide" id="slide1">
    <h1>Slide 1</h1>
    <p>Scroll down to see the snap effect.</p>
  </section>
  <section class="slide" id="slide2">
    <h1>Slide 2</h1>
    <button id="btn">Log Scroll Position</button>
  </section>
</div>
<script>
const scroller = document.getElementById("scroller");
document.getElementById("btn").addEventListener("click", () => {
  console.log("Current Scroll Position: " + scroller.scrollTop);
  scroller.style.scrollSnapType = "none";
  alert("Snapping disabled via JS style object.");
});
</script>

Pro Tip

You can create a high-end, full-page vertical scroller with zero JavaScript by applying scroll-snap-type: y mandatory to the HTML or Body tag and scroll-snap-align: start to your section tags. It provides a native app-like feel with minimal code overhead.

Deep Dive

Think of scroll-snap-type as a magnet for your scrollbar. When you set this on a parent container, you are telling the browser to grab the scroll position and pull it into a specific alignment when the user lets go. It requires two parts: the parent container needs scroll-snap-type to define the axis and strictness, and the child elements need scroll-snap-align to define where the magnet is located (start, center, or end). If you choose mandatory, the browser will never let the scroll rest between two items; it will always jump to the nearest point. If you choose proximity, it feels more natural, only snapping if the user stops their scroll near a target.

Best Practices

Use proximity when you want a helpful nudge for the user, like in a list of cards where they might want to stop anywhere. Use mandatory for full-screen slides, carousels, or page-flipping interfaces where it would look broken to stop halfway between sections. Always ensure the parent container has overflow-x or overflow-y set to auto or scroll, otherwise there is no scrolling for the snapping to act upon.

Common Pitfalls

The biggest mistake is forgetting to set scroll-snap-align on the child elements; without that, the parent has no targets to snap to. Another common issue is using mandatory on content that is taller than the viewport. If a section is too long and you use mandatory snapping to the top, the user might be physically unable to scroll down to read the bottom of that section because the browser keeps snapping them back to the start.

Accessibility

Mandatory snapping can be disorienting for users with motion sensitivity. Ensure that keyboard navigation works correctly, as some browsers might not scroll smoothly to snap points when using arrow keys. Never hide content behind a snap point that cannot be reached by all input methods.

Dev Data Table: scroll-snap-type property

default none
animatable no
inherited no
experimental no
year_intro 2016
year_standard 2018
js_syntax_1 element.style.scrollSnapType = "x mandatory";
js_syntax_2 element.style.setProperty("scroll-snap-type", "y proximity");
js_note When manipulating this property in JavaScript, the camelCase version scrollSnapType is used on the style object.
browsers { "Chrome": 69, "Edge": 79, "Firefox": 68, "Safari": 11, "Opera": 56, "Chrome Android": 69, "Safari on iOS": 11, "Samsung Internet": 10.1, "Opera Mobile": 48 }
results render here...