Swipe Views with CSS Snap Points: Building a More Efficient Mobile Web Navigation

Update 15 — August — 2018: Chrome has shipped CSS Scroll Snap Points specs and will be enabled by default as of Chrome 69, Web Developers can now use this feature on all of Edge, Chrome, Firefox and Safari 🎉.

Update 01 — April — 2018: Fixed some typos — Broke down the problems of traditional carousel into clearer points — broke down the advantages of Snap Points into clearer points — Added future work I will be doing on this topic.

The mobile web has been making a lot of progress in the last year or two and I have happily replaced few native apps on my phone with their web alternatives and today I’m a full-time user of Twitter Lite and Instagram PWA.

For a long time the responsive mobile web has been hierarchical however, native apps has flattened the vertical hierarchies in their main views and implemented a very popular pattern sometimes called “horizontal paging” which provides the users with an efficient horizontal navigation from one tab to another using a simple left or right gestures and makes the relevant data or content in different app screens more accessible.

Not to my surprise, Twitter and Instagram PWAs — that I use daily as I mentioned earlier and they are 2 of my all-time favourite web apps — have brought in their native apps like navigation bars. Also not to my surprise, there is no swipe gesture and the absence of swipe gestures is not an app limitations but unfortunately a web platform limitation in my opinion.

Traditional Web “Carousel” Problems

The traditional, cross-browser carousel problems starts with the implementation requirements:

  • A wrapper with overflow hidden.
  • A wide wrapper of (number of screens*screen width) pixels.
  • A minimum of 7 different events listeners: mousedown, mouseup, mouseleave, mousemove, touchstart, touchend, touchmove.
  • On mouse or touch move we translate the wider container.
  • CSS will-change:transform and whatever other magic we got and can add there to make that transition as smooth as possible.

Following those steps should give us a decent carousel with 50 bugs or so that is probably good enough for a hero banner but if we want to use it for an app views that have complex children layout, posts lists, comments, images, etc.. it will not do an amazing job for many reasons:

  • Code complexity caused by having to deal with 7 different mouse and touch JavaScript events.
  • If any children elements are meant to receive mouse or touch events, deciding if the parent should propagate or act first can be tricky and a further assistance form pointer-events and touch-events might be helpful to allow or block specific elements from receiving mouse or a touch events at some cases.
  • Determining where the transition has to stop can also be tricky especially for different size children or on the container’s resize where the children size might change in which case a JavaScript recalculation is required.

CSS Scroll Snap Points To The Rescue

CSS scroll snap points module helps us specify where a container’s scroll port should stop after the scrolling operation has been completed, read more about it on MDN and check Can I Use for browser compatibility. It is coming along nicely in all major browsers, the only no-support flags are in Chrome but the good news it’s being actively and almost daily worked on, check out the bug smashing progress here (Go Chrome!).

Few Problems CSS Scroll Snap Points Will Solve

  • Reduce the JavaScript code complexity as there’s no need to listen to mouse or touch events anymore.
  • More efficient way to respond to children elements mouse & touch events since the parent does not require them anymore, there is no need to check on whether the parent wrapper has to respond or propagate.
  • Ability to deal effortlessly with different size children or after children widths changes due to a container resize for example. CSS Snap Points will always snap to the begging of the child element or to any point we specify using scroll-snap-coordinate property without needing to calculate the element’s widths.

Simple CSS Only Swipe Views Demo

If you using Edge, Safari or FireFox you can try my swipe views pen with CSS Snap Points:

Alternatively, you can check out this video I recorded of that pen:

CSS Snap Points Look Promising

Snap Points seem to have everything I need to replace a 100 lines of carousel code that needed 7 different JavaScript events and a bunch of math and logic with literally 4 lines of CSS and the results are certainly more natural and performant.

overflow-x: auto;
scroll-snap-coordinate: 0 0;
scroll-snap-points-x: repeat(100%);
scroll-snap-type: mandatory;

Advanced Usage: CSS Grid with CSS Snap points

CSS Grid + CSS Snap Points = 0 JavaScript, 0 CSS Media Query Responsive Swipe Views

CSS Grid has brought a lot of flexibility and magic to the way browser layout works, here’s a pen where I made a fully responsive Swipe Views (Carousel) with CSS Grid and Snap Points where neither JavaScript nor CSS media queries are required to achieve the responsiveness.

Thumbs Up

In my opinion, Snap Points seems to be an option for building Swipe Views that can make browsing a lot of web apps’ home screens and consuming their content a more fluent experience and can also help us get rid of tens of lines of JavaScript code if all we needed was a simple minimal web carousel.

I have plans to experiment further more with them in the near future and learn more about their “cons” in real-world applications. I will also experiment with building a performant dynamic carousel and then will most likely publish a part 2 post as a follow-up.

Until then, if you have experimented with CSS Snap Points module, have a comment or anything to add to this post please comment below!

Thank you for reading 💚.