Scrollbar Reflowing

Avatar of Chris Coyier
Chris Coyier on

DigitalOcean provides cloud products for every stage of your journey. Get started with $200 in free credit!

This is a bit of advice for developers on Macs I’ve heard quite a few times, and I’ll echo it: go into System Preferences > General > Show scroll bars and set to always. This isn’t about you, it’s about the web. See, the problem is that without this setting on, you’ll never experience scrollbar-triggered layout shifts, but everyone else with this setting on will. Since you want to design around not causing this type of jank, you should use this setting yourself.

Here’s Stefan Judis demonstrating that usage of viewport units can be one of the causes:

There, 100vw causes horizontal overflow, because the vertical scrollbar was already in play, taking up some of that space. Feels incredibly wrong to me somehow, but here we are.

Stefan points to Kilian Valkhof’s article about dealing with this. The classic fixes:

The easy fix is to use width: 100% instead. Percentages don’t include the width of the scrollbar, so will automatically fit.

If you can’t do that, or you’re setting the width on another element, add overflow-x: hidden or overflow: hidden to the surrounding element to prevent the scrollbar.

Kilian Valkhof, “How to find the cause of horizontal scrollbars”

Those are hacks, I’d say, since they are both things that aren’t exact matches for what you were wanting to do.

Fortunately, there is an incoming spec-based solution. Bramus has the scoop:

A side-effect when showing scrollbars on the web is that the layout of the content might change depending on the type of scrollbar. The scrollbar-gutter CSS property —which will soon ship with Chromium — aims to give us developers more control over that.

Bramus Van Damme, “Prevent unwanted Layout Shifts caused by Scrollbars with the scrollbar-gutter CSS property”

Sounds like the trick, and I wouldn’t be surprised if this becomes a very common line in reset stylesheets:

body {
  scrollbar-gutter: stable both-edges;
}

That makes me wonder though… it’s the <body> when dealing with this at the whole-page level, right? Not the <html>? That’s been weird in the past with scrolling-related things.

Are we actually going to get it across all browsers? Who knows. Seems somewhat likely, but even if it gets close, and the behavior is specced, I’d go for it. Feels progressive-enhancement-friendly.