Horizontal or vertical scroll snap in CSS
Scroll snapping in CSS has been around for a while and it's a great way to create modern interactive experiences. It consists of a handful of properties that allow you to create a scrollable container that will snap on elements when scrolling, either horizontally or vertically.
Scrollable containers that snap
To create a scrollable container that snaps on elements when scrolling, you can use the scroll-snap-type property to control the snap axis. This property can be set to x for horizontal scrolling or y for vertical scrolling. You can also set it to both to enable both horizontal and vertical scrolling.
If you're working with the new Logical Properties you can use block for vertical and inline for horizontal. In this article, however, we'll focus on the more traditional x and y values.
/* Horizontal scroll snap */
.scroll-snap {
scroll-snap-type: x mandatory;
}
/* Vertical scroll snap */
.scroll-snap {
scroll-snap-type: y mandatory;
}
Apart from the snap axis, you can also specify the snap strictness with scroll-snap-type. The mandatory value will snap the container to the nearest snap point, while proximity will snap the container to the nearest snap point if it's close enough (default).
Snap alignment
You can also control the alignment of the snap points using the scroll-snap-align property. This property can be set to start, end, center, or none.
/* Snap to the start of the element */
.scroll-snap > .element {
scroll-snap-align: start;
}
/* Snap to the center of the element */
.scroll-snap > .element {
scroll-snap-align: center;
}
/* Snap to the end of the element */
.scroll-snap > .element {
scroll-snap-align: end;
}
Scrolling over the edge
To prevent the default browser behavior when reaching the end of the scrollable container, you can use the overscroll-behavior property. This property can be set to auto, contain, or none.
The contain value is usually preferred as it allows the scroll snap to work as expected when scrolling over the edge of the container.
Depending on your use case, you can use overscroll-behavior-x and overscroll-behavior-y to control the behavior on the horizontal and vertical axes respectively, or even overscroll-behavior-inline and overscroll-behavior-block if you're using Logical Properties.
/* Horizontal scroll snap */
.scroll-snap {
scroll-snap-type: x mandatory;
overscroll-behavior-x: contain;
}
/* Vertical scroll snap */
.scroll-snap {
scroll-snap-type: y mandatory;
overscroll-behavior-y: contain;
}
Horizontal scroll snap
Putting everything together, we can create a horizontally scrollable container that will snap on elements when scrolling. At its core the HTML and CSS is quite simple. All you need to do is set the scroll-snap-type to x mandatory and the overscroll-behavior-x to contain. You can decide on the value of your scroll-snap-align based on your design.
See the embedded CodePen
<div class="horizontal-snap">
<!-- Add your content here, use .element for snap points -->
</div>
.horizontal-snap {
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x mandatory;
}
.horizontal-snap > .element {
scroll-snap-align: center; /* or start, end */
}
Vertical scroll snap
Similarly, a vertically scrollable container that snaps on elements when scrolling can be created by setting the scroll-snap-type to y mandatory and the overscroll-behavior-y to contain. You can again decide the value of scroll-snap-align based on your design.
See the embedded CodePen
<div class="vertical-snap">
<!-- Add your content here, use .element for snap points -->
</div>
.vertical-snap {
overflow-y: auto;
overscroll-behavior-y: contain;
scroll-snap-type: y mandatory;
}
.vertical-snap > .element {
scroll-snap-align: center; /* or start, end */
}