Fixing Smooth Scrolling & Page Search (updated!)
Yesterday, as I was browsing my Twitter timeline, a tweet from Chris Coyier popped up, in which he mentioned feedback he got for one of his CSS Tricks experiments. It went as follows:
Anecdotal thing: when I had this on @CSS, I had SO MANY reports of people annoyed that when they did "find on page" and ⬆️⬇️ through the results, the smooth scrolling was slow and annoying. Unfortunately, you can't control the speed or when it happens. https://t.co/HAio46bYQt
— Chris Coyier (@chriscoyier) January 5, 2021
Apparently Chris had once switched out JavaScript-based smooth anchor scrolling in favor of a more modern, purely CSS-based solution. All you need to do is slap a scroll-behavior: smooth
on html
and all of a sudden scrolls to different places on the page happen smoothly. And that's great!
Page Search #
Sadly, as Chris points out in his tweet, native smooth scrolling negatively affects the UX of page search when cycling through its search results:
Smooth scrolling is consequently applied to everything. Always. Even when cycling through the browser's page search results. At least that's the case for Chromium. So for the page search it would be desirable for the browser to make an exception to that rule and to deactivate smooth scrolling.
Until the Chromium team fixes it, here is a trick how to solve the problem on your own with a little bit of extra CSS --and HTML--.
The Solution #
First you need to move your assignment of scroll-behavior
from html
selector to html:focus-within
. This will ensure that smooth scrolling is only active while the focus is within the page. Sadly Chrome and Firefox, upon clicking an on-page anchor link, both first assign and then remove focus from the document. Therefore you need to flank the above with two (identical) time-limited animations that force smooth scrolling onto the document for a certain period of time after the click.
@keyframes smoothscroll1 {
from, to { scroll-behavior: smooth; }
}
@keyframes smoothscroll2 {
from, to { scroll-behavior: smooth; }
}
html {
animation: smoothscroll1 1s;
}
html:focus-within {
animation-name: smoothscroll2;
scroll-behavior: smooth;
}
Now everytime the user interacts with the surrounding browser interface, as is the case with the page search, smooth scrolling will be disabled and jumping to the results will be instantaneous.
And that's it. Problem solved!
2021/01/17 Update: My initial solution broke smooth scrolling on a perfectly working Firefox (due to this long standing bug). So I reworked the code. The CSS got more complex, but on the winning side you don't need to add tabindex
es to your HTML any more.
Thanks go out to Matthias Ott and Stefan Judis for pushing me to publish this post ❤
The cover image of this post is Graceful Ballet Dancer by Master1305