I wish I could control CSS scroll-snap with Javascript

So I love CSS scroll-snap. I think it’s really, truly amazing.

Sure, yes, it lets you make carousels that aren’t janky JavaScript nightmares—but I think they’re more than that because now we can make webpages feel more like, well, Powerpoint. And that’s an extremely exciting thing for writers! You can make websites behave like pages or comic books or photo books! You can control the pace of your work with nothing more than just a sliver of CSS.

To get started you’ll need to make a container with some slides:

<div class="container">
<div class="slide">
<!-- content goes here -->
</div>
<div class="slide">
<!-- content goes here -->
</div>
</div>

And then some CSS...

.wrapper {
display: flex;
gap: 10px;
overflow-y: scroll;
scroll-snap-type: x mandatory;
width: 100vw;
height: 100vh;
}

.slide {
scroll-snap-align: start;
}

And then you’re basically done! In this example, x mandatory will force this carousel to snap left->right when you move horizontally with your mouse (and heck, in Chrome you can even use the directional keys to move back and forth between slides!).

Check out this quick demo I made last night—and try scrolling to the right:

See the Pen X100v by Robin Rendle (@robinrendle) on CodePen.

But! One problem with this design is that users here won’t know that they can scroll right. I could put a big arrow or something on the first slide but what would be even neater is if I could use JavaScript to hijack the scroll maybe. So that when folks scroll down then it pushes folks to the next slide in the series. Maybe that would be disorienting as heck but I think it would be better than just doing...nothing, right?

The problem here is that I don’t think we can do this with JS today. As far as I can tell there’s no scroll-snap API where I can order JS to skip to slide 4 (which could be handy if this website had a table of contents). And I can’t hijack the scroll and say “next slide please”!

Alas, there’s only this proposal from Adam Argyle which looks like it would perfectly solve this problem:

container.scrollTo({
left: "snap-first",
top: "snap-first",
behavior: "instant",
});

Wonderful! This is exactly what I want. Shame that I can’t use it today though.