Recently I needed a way to detect support for a media query in CSS and Javascript. To detect if a browser supports a certain CSS feature, you can use @supports () { … }, but that doesn’t work for media queries. In this article I’ll show you how you can detect support for media queries […]
Preventing smooth scrolling with JavaScript
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:
smooth
, for smooth scrollingauto
, which does whatever the page’sscroll-behavior
is set to.
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:
smooth
: always smooth scrollauto
: use what the scroll-behavior for an element is set to
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.