Happy holiday folks! All the best from us at Digitpaint

Day 17

Snappy scrolling with scroll snap points

Hacking smooth scrolling galleries that 'snap' to each frame with JavaScript will soon be a thing of the past. With CSS Scroll Snap Points you can create this experience for your user with just a little bit of plain 'ol CSS.

In this demo you can scroll through the image-gallery horizontally and see how the slides 'snap' so they'll stay nicely in view. Only works in Safari 11+ right now.

The CSS Scroll Snap Module

The CSS Scroll Snap Module allows you to control how a scroll container will snap to a part of the content after the user scrolls vertically or horizontally. This is especially useful for touch devices where the user can quickly scroll through large pieces of content. You can, for example, create smooth scrolling interfaces for a full page photo gallery, images on a page or even slides in a presentation.

Before the Scroll Snap Points Module were born, we used JavaScript (and most often jQuery) to create such a 'snappy' scrolling interface. With the availability of this native CSS technique, we can do all of this with a lot less code (and that of course makes us as developers happier).

The CSS Scroll Snap Module is still under development, and not yet widely supported by all browsers. Specs have changed over time, and some browsers support only properties from an older version of the spec. In this article, we will only discuss the most recent spec, which at the time of writing are only supported by Safari 11 and Safari iOS 11.2.

Hands-on with scroll snap points

To set up snap point scrolling you define a scroll container, and tell it's inner elements at which point to snap to the container edges. Let's look at this hypothetical slider.

<ul class="container">
  <li class="item">Item</li>
  <li class="item">Item</li>

Properties of the scroll container

On the container you can set the following scroll snap properties.

This property tells the container:
  1. that it is a scroll snap container
  2. how strictly the container should snap to it's inner elements
  3. what axis (axes) are affected by snap positions
This is a shorthand property, much like the normal padding. With it, you can define the offsets from the container to the snap elements as you scroll.

In the code example below, the scroll container snaps to snap positions on its horizontal axis (the x value), and it will always land on a snap point, even after a small scroll (the mandatory value).

.container {
  scroll-snap-type: x mandatory;
  scroll-padding: 2rem;

The default strictness value for scroll-snap-type is proximity, which tells the scrolling container only to move to the next snap point when the user has scrolled close to the elements scroll-snap-align point.

Properties of the child elements

On the individual child elements inside the snap container you can define

This is also a shorthand property (just like margin), and defines the offset of the current snap element against the scroll container.
Used to declare how an element's scroll snap margin aligns with its scroll container. Possible values are: [none | start | end | center] for both the x and y axis. If only one value is given, it will read as a shorthand for both values.
Tells the snap container if it may (normal) or must not (always) pass over a snap position during scrolling.

In our demo we set scroll-snap-align to center none, as you can see in the code below. This basically means that the elements will horizontally center in the snap container.

.item {
  scroll-snap-margin: 2rem;
  scroll-snap-align: center none;
  scroll-snap-stop: normal;

Browser compatibility

Currently, only Safari supports the latest specs of the CSS Scroll Snap Module. IE, Edge and Firefox support (parts of) an older version of the spec. Chrome plans to implement this feature in the future.

  • Safari 11+
  • iOS Safari 11.2+
  • FireFox Old spec
  • ie Old spec (partial)
  • Edge Old spec (partial)

More detailed information on caniuse.com

Learn more

Demo source code

Do you want to dig in the nitty-gritty of this demo, check out the source files:

Back to home