HTML & CSS
Article

Intuitive Scrolling Interfaces with CSS Scroll Snap Points

By Simon Codrington

Scroll Snap Points are a native CSS-only technique that you can use to create layouts where your content is easily scrolled or panned. With this new feature you can easily control how your content will scroll and how it will ‘snap’ to the correct locations (letting you create features such as pagination with ease).

Historically developers have used JavaScript (often jQuery) to create perfect smooth-scrolling, snapping interfaces. While these work just fine, having a native CSS approach that does essentially the same thing is always better.

The specification for Snap Points is still relatively new (and under development); however it’s supported by a few browsers and is stable enough for us to start playing around with.

Creating a cool scrolling region with just CSS snap points

An Overview of Snap Points

Snap point scrolling works by defining a Scroll Container element and then setting each of its inner elements to be Snap Points. Once these elements have been set, normal scrolling will be modified so that as users scroll/pan they will be snapped from one snap point to the next.

The main element that holds all of your other elements you wish to scroll between is called the Scroll Container. This is our main element and the majority of the snap-related properties will be set here. We can define:

  • How tall/wide the container will be
  • On which axis/axes the container will scroll (i.e. X, Y, or both)
  • The strength of the snap elements and how they will react to scrolling
  • The positions/offsets from the container to the snap elements as you scroll

The elements inside the scroll container will become our “Snap Points”. It’s this content that will be scrolled/panned to when we interact with the container. For an individual snap point you will define:

  • The offset of the current snap element against the scroll container.

Horizontal scrolling made easy, one image at a time

Vertical sliders are great for breaking up your content

The Scroll Snap Points Properties

Getting Snap Points to work in your projects involves only a few CSS properties. Let’s outline these below and then later when can look at a few examples that showcase how they work.

scroll-snap-destination

This property is set on the scroll container and it defines the X position and Y position values (relative to itself) that the elements inside will snap to. You use this property to tell the container exactly where its elements will be snapped to.

Here are the possible values:

  • unset – Used to declare that this container is not a scroll container (by default no containers are unless you set it)
  • position – You must set both the X and Y position or the browser will ignore your property
    • Value can be in pixels such as scroll-snap-destination: 50px 100px; which tells the browser that it will snap elements from 50px to the left and 100px from the top.
    • Value can be a set of percentages such as scroll-snap-destination: 0% 100%; which tells the browser that it will snap elements from 0% to the left and 100% from the top.
    • Value can also be other allowed units such as scroll-snap-destination: 0vw 50vw which tells the browser that it will snap elements from 0% of the current viewport height to the left and 50% of the current viewport height to the top.

Let’s look at a few visual aids so you can see how this property works (as it’s one of those properties you will need to adjust until you get the correct effect).

scroll-snap-destination: 0% 0%
Setting the scroll destination to 0% will ensure that all inner elements snap to the leading left edge of the container.

scroll-snap-destination: 0% 0%

scroll-snap-destination: 50% 0%
Here we set the scroll container to snap content at 50% of its width. This means that as we scroll, the active element will snap to the left hand side of the 50% position.

scroll-snap-destination: 50% 0%

scroll-snap-destination: 100% 0%
This time our snap destination is 100%. This means each of the inner elements will snap to the right side of the container as we scroll.

scroll-snap-destination: 100% 0%

scroll-snap-coordinate

This property is defined on each snap element and determines the X position and Y position values where this element will snap to. This property works together with the scroll-snap-destination declared on the container and determines the element’s offset from the snap point.

  • none – There will be no offset for this element. It will snap directly where the scroll container has defined.
  • position – You must set both the X and Y position for this to work.
    • Value can be in pixels such as scroll-snap-coordinate: 100px 0px, which tells the browser the snap element will be offset by 100px from the left edge of the snap point and 0px from the top.
    • Value can use percentages such as scroll-snap-coordinate: 25% 0%, which tells the browser that the element will be offset by 25% of its width from the left edge of the snap point (and also offset by 0% from the top).
    • Value can also be other allowed measurements such as scroll-snap-coordinate: 15vw 15vw which will mean the snap element is offset by both 15% of the viewport width from the top and left of the snap container.
    • position (multiple) – You can also set multiple coordinates for the snap element by passing set pairs such as scroll-snap-coordinate: 50% 0%, 100% 0% which tells the browser this element will snap to 50% of its width from the leading left edge of the snap point (and 0% from the top) and it will also snap to 100% of its width from the snap point edge (and 0% from the top). This is useful because sometimes at the start or end of a scrolling list an item should snap in multiple places, not just one.

If this property is not set, the element will simply snap as defined by the scroll container. If you do set the scroll-snap-coordinate property, the element itself will offset itself depending on what you enter. This is mainly used so you can position your elements just right (or to allow other content to peek through the viewport).

Let’s look at some examples for scroll-snap-coordinate with a description of what each one does:

scroll-snap-coordinate: 50% 0%
This tells the browser that the element should snap towards the set edge of the scroll container, but that its snap should offset itself by 50% of its width to the left. This basically means that it will center align itself to the snap point.

scroll-snap-coordinate: 50% 0%

scroll-snap-coordinate: 0% 0% and scroll-snap-coordinate: 0% -50px
Here we see a side by side comparison so we can look at what happens when you specify that your elements will have a negative offset.

For the example on the left, we don’t set the coordinate property (it will just snap to its parent’s container). The example on the right, we explicitly tell the browser to offset the vertical snap position by -50px (which lets another element before it sneak in).

scroll-snap-coordinate: 0% 0% and scroll-snap-coordinate: 0% -50px

You can adjust the coordinate properties until your snaps work for your interface.

scroll-snap-type

This property determines how strongly the scroll container will snap to its inner elements. Here are the possible values:

  • none – The scroll container ignores all snap points (scrolls normally)
  • mandatory – The scroll container will move to the next snap element during even a small scroll or single click on the scroll bar. The scroll container will immediately move and align itself with the snap point. This is best used you want to be 100% sure that as your user scrolls they will always snap to the next element.
  • proximity – The scroll container will move to the next snap element only if it is somewhat close to a snap point. As the user scrolls or clicks on the scroll bar, the scrolling motion will seem to be normal, however if the user gets close to the edge of a snap element it will then snap into place. This is best used when you want your users to be able to scroll freely, but would like the scroll container to snap to content if it gets close enough (somewhat like a magnet).

I find using mandatory works the best as it’s a hard forced snap, however proximity also works well with its softer snap between zones (the downside is there is no way to customize how sensitivity of when it will snap)

scroll-snap-points-x and scroll-snap-points-y

If you view the current version of the spec you’ll notice it includes descriptions for the scroll-snap-points-x and scroll-snap-points-y properties. As pointed out in a notice on MDN, these two properties have been deprecated and so they’re not included in the editor’s draft of the spec. So I won’t go into details on those here.

Practical Examples with Scroll Snap Points

Now that we’ve covered the basics, lets jump into some examples so you can see how this all works in practice.

Each of the examples below has its own CodePen with even more notes that discuss exactly how the scrolling works (plus a few little design bugs you might run into). Feel free to fork your own copies and create something fun with them.

A full-width interactive section scroller

The great thing about CSS Snap Points is how easy they are to implement. All you do is define your container, its elements, and how it will snap. Look at the additional full-width container slider I have built below. Here’s what it contains:

  • Full-width outer container (using vw and vh units)
  • Each section has its own dynamic height, not a set height with px
  • On scroll, each section is snapped to the top of the scroll container

See Full Page Demo

This gallery contains images of all different shapes, sizes and aspect ratios. Here’s a description:

  • Handles different image sizes and aspect ratios (so a real life example)
  • Snaps content to the center of the container
  • It’s responsive. Works based on either an auto width / height with additional maximums set by max-width / max-height. Images are adjusted to fit within (and their scroll positions updated).
  • Uses a combination of scroll-snap-destination and scroll-snap-coordinate to handle the snapping

See the Pen Snap Points Demo: Scroller with different sized images by SitePoint (@SitePoint) on CodePen.

And here is the vertical scrolling example:

See the Pen Snap Points example: Vertical scroller with different sized images by SitePoint (@SitePoint) on CodePen.

For this example, all of our images are the same size. In addition, the images themselves will be responsive, using bottom padding to make them perfectly square. As the viewport resizes, they will resize accordingly (up to a set maximum width).

  • Fully responsive, width 100% with padding 0% to create a perfectly responsive square gallery
  • Shows one image at a time by using eithersnap-scroll-points-xor snap-scroll-points-y to move horizontally or vertically through the gallery.

See the Pen Snap Points example: Responsive Horizontal Scroller with same sized images by SitePoint (@SitePoint) on CodePen.

And here is a vertical example:

See the Pen Snap Points example: Responsive Vertical Scroll Gallery with Same Sized Images by SitePoint (@SitePoint) on CodePen.

Browser Support for Snap Points

Details on browser support for Snap Points can be found on Can I Use, but here’s a quick summary, as of this writing:

  • Firefox 39+ – Fully supported for current specification.
  • IE10 – Requires a touch device for this to work and requires the -ms prefix.
  • IE11 – Can use snap points on either a touch screen, mouse, keyboard, or trackpad and requires the -ms prefix.
  • Edge – Much like IE10 and IE11, supports snap points with the -ms prefix
  • Safari 9 – Supports snap points but doesn’t support the none keyword for the scroll-snap-coordinate property. Also, doesn’t support length keywords of top, right, left, or bottom for the scroll-snap-destination and scroll-snap-coordinate properties.
  • iOS Safari 9 – Requires -webkit prefix (this is the only mobile browser that supports Snap Points)

Basically we have great support if you’re on Firefox, average support on Internet Explorer / Edge and basic support on Safari. Chrome Canary (Google’s bleeding edge version of Chrome) has support for Snap Points so it should find itself in stable Chrome soon.

Sadly If you’re hoping to use this on mobile apps, it might take a while before most of the major browsers support it.

If you’re interested in using Snap Points today, you can try a polyfill by Clemens Krack.

Conclusion

I hope you now you have a fairly solid understanding of CSS Snap Points and how they can be leveraged to create interesting and easy to manage user interfaces. Going forward, support will spread fully to Chrome and IE and then we can start pushing for its inclusion in upcoming projects.

I’d love to hear from you if you end up implementing snap points in one of your projects!

Simon Codrington
Meet the author
I'm a designer, developer and overall web enthusiast. I love everything to do with web and design and my passion revolves around creating amazing websites for my clients. Focusing primarily on WordPress, I create themes, plugins and solutions with my team over at Web Bird Digital.
  • PVgr

    Excellent article Simon! Somehow I haven’t read anything about snap point before…

    • simon codrington

      Thanks @PVgr

      Yea, it seems like one of the random CSS properties that never get any love & attention.

      It works really well in FireFox (especially in combination with smooth scrolling), I’m waiting for Chrome to bring support but I can’t really find any specifications on when it’s coming.

      I’m also working with the modernizer guys to get some decent tests set up so you can detect support and fall back accordingly :)

  • Antonella

    Fantastic article, Simon! I haven’t kept up with CSS Snap Points and wasn’t aware of the fact that browser support, although not robust, is quite decent and hopefully getting better. Great idea to get the Modernizr guys on board with this.

    • simon codrington

      Thanks for reading Antonella :)

      The support is actually really great on FireFox, supporting most of the specification early. Safari 9 for both desktop and mobile offer some support (though the lack of scroll-snap-coordinates is a little disappointing). Looking at IE it’s a bit disappointing that it still relies on the older x and y destination properties which are being phased out.

      I’m waiting for Chrome to pick up and run with this as once they support it a good chunk of the population will be able to enjoy snap scrolling.

      I’ve managed to work with the modernizer guys to add a scroll snap test. I’m also seeing if they can add a second test so that you can test for complete support like what FireFox offers, or just basic support like what Safari offers: https://github.com/Modernizr/Modernizr/issues/1800

  • M S i N Lund

    Seems like one of these things that will let designers create sites that work even worse on big screens.

    Like pages that would have fit just fine on a modern UHD-screen, but gets spread out thin, so you have to scroll, and then they add this to make all that extra scrolling more “interesting”.

    I really miss the times when every time you upgraded your screen, you got more space to view more content on, instead of just bigger letters and more whitespace.

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!