Kilian Valkhof

Building tools that make developers awesome.

Preventing smooth scrolling with JavaScript

CSS & HTML, Javascript, 31 January 2022, 3 minute read

With scroll-behavior: smooth in your CSS you can tell browsers to animate scrolling to different parts of your site, for example when linking to an ID on a page. The javascript scrollTo API has a behavior option that lets you turn on smooth scrolling for one specific scroll regardless of the CSS being set or not.

But what if you want to do the opposite: turn smooth scrolling off for a specific scroll even if it’s turned on in the CSS?

You see, the behavior property for the scrollTo API comes with two options:

MDN says that auto “happen[s] instantly in a single jump”, but that’s not the case in browsers at the moment.

If you use scroll-behavior: smooth in your CSS, make sure to wrap it in a @media (prefers-reduced-motion: no-preference) { } media query for accessibility.

And according to the CSSOM spec it links to, those are the only two options available.

window.scrollTo({
  top: 1000,
  behavior: 'auto' | 'smooth'
})

And with auto as the value, the specification explains that the behavior should fall back to the value specified in the CSS.

So if a page has smooth scrolling turned on in your CSS are you just out of luck? behavior: 'smooth' will smooth scroll explicitly, and behavior: 'auto' will smooth scroll because that’s the page behavior. Do you have to overwrite the CSS before scrolling, and then setting it back after you’re done?

Luckily, you don’t.

It turns out MDN is running a little ahead of browsers, because it’s linking to the current editors draft, not the working draft. In the working draft there’s an extra option: ‘instant’, which both Chrome and Firefox support.

Unfortunately, the current Editors draft removed the instant value.

Whats the difference between an editors draft and a working draft?
An editors draft is the latest version of a specification draft, being updated as an editor works on it. A working draft on the other hand has been published for review by the community.

But what about that instant value?

When setting behavior to instant, the scrollTo function will scroll to the new position instantly without any animation regardless of what scroll-behavior has been set to in the CSS, at least in Chrome and Firefox. Hooray!

window.scrollTo({
  top: 1000,
  behavior: 'instant'
})

With behavior: 'instant' we can achieve what we want: disable smooth scrolling for a specific scroll, even if scroll-behavior on the scrolling element has been set to smooth.

Add it (back) into the spec?

I’m not the first to notice this issue, as you can see in this 2019 GitHub issue asking for “instant” to be put back in. Clarify scroll-behavior: “auto” #3497.

I think it’s clear that forcing an instant scrollTo should be part of the API. The current editors draft seems to specificy the following situations:

And no explicit way to prevent smooth scrolling. Given both Firefox and Chrome are implementing the instant feature, it seems wise to add it back into the specification.

Polypane browser for responsive web development and design Hi, I'm Kilian. I make Polypane, the browser for responsive web development and design. If you're reading this site, that's probably interesting to you. Try it out!