The Downsides of scrollbar-gutter: stable; (and one weird trick)

Chris Coyier Chris Coyier on

The esteemed Zach (Leatherpants), blogged about the virtues of scrollbar-gutter: stable;, suggesting it might be good in a starter stylesheet. (Hey, I’ve got one of those.) The thing that it solves is content-shifting. If you have a page that, upon first render, doesn’t have a vertical scrollbar, but more content loads later and gets one, it can shift content horizontally to make room for the scrollbar, which is a smidge annoying. That’s assuming your OS setting has always visible scrollbars enabled. (I do in my macOS settings, I prefer it.)

Also, navigating from a page that doesn’t require vertical scrolling to one that does (or vice versa) causes a layout shift to the tune of one scrollbar width.

Using scrollbar-gutter: stable; (supported everywhere) means that the browser will “reserve space” for a scrollbar and thus totally remove the layout-shifting downsides mentioned above.

You can see the visual shift when we add content that overflows vertically. But if we flip on scrollbar-gutter: stable; the content stays steady when it goes back and forth between overflowing and not.

Notice in the video above though, the shifting-fix is accomplished by putting the space of the scrollbar there. You can see it’s quite literally a white bar. This only seems to happen when the page is rendered in an <iframe> like it is on CodePen, but I still find it highly obnoxious and a downside (as there is no way I’ve found to make it not a white, or dark-in-dark-mode, bar).

Here’s that demo:

Fortunately, the “literal white bar” problem isn’t there on regularly-rendered pages (outside of an iframe), as that would be an instant deal breaker.

The remaining problem is centering.

The space that is reserved for the maybe-maybe-not scrollbar cannot be factored into centering (like margin: auto; and whatnot).

Screenshot showing a content area with a gray background, below which there is a large white space indicating the absence of a vertical scrollbar, accompanied by red arrows pointing towards the white space.
😭

So if you really need to visually center something, it’ll be fine-ish if there is a scrollbar, and noticeably not-centered-looking if there isn’t. Boooo.

To me, this is just annoying enough to not put it in a starter stylesheet.

But!

Just for fun we could look at a newfangled CSS alternative. My big idea here is that we actually can tell if the page is overflowing and has a scrollbar or not these days. We can do this via scroll-state queries.

So we make the whole page a scroll-state container then watch for when it is scrollable and push the whole page in a little bit the same width as the scrollbar.

html {
  container-type: scroll-state;
  
  --scrollbar-width: 25px;
  &::--webkit-scrollbar {
    width: var(--scrollbar-width);
  }
}

body {
  @container scroll-state(scrollable: block) {
    padding-left: var(--scrollbar-width);
  }
}Code language: CSS (css)

Notice I’m attempting to wrestle control over the width of the scrollbar there using those non-standard vendor prefixes. But 25px is the generally standard width of the scrollbar anyway. But that could change if a user set something like scrollbar-width: thin; or something. Makes me wish there was an env() variable or something that always reflects the width of the scrollbar at any DOM level. Anyway, if you have Chrome, you can see this approach working here:

Certainly the scrollbar-gutter approach is easier and far better supported, but it’s neat to know there are future options.

Wanna learn CSS from a course?

Frontend Masters logo

FYI, we have a full CSS learning path with multiple courses depending on how you want to approach it.

7-Day Free Trial

Leave a Reply

Your email address will not be published. Required fields are marked *

$916,000

Frontend Masters donates to open source projects through thanks.dev and Open Collective, as well as donates to non-profits like The Last Mile, Annie Canons, and Vets Who Code.