Prevent unwanted Layout Shifts caused by Scrollbars with the scrollbar-gutter CSS property

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.

Let’s take a look.

~

👨‍🔬 The CSS features described in this post are currently only supported in Chromium 88+ with the #experimental-web-platform-features flag enabled through chrome://flags.

💥 To keep your primary Chromium install clean, I recommend you do not set this flag in Chromium Stable, but resort to Beta / Canary builds.

~

Table of Contents

  1. Classic vs. Overlay Scrollbars
  2. The Problem
  3. The Solution: scrollbar-gutter: stable;
  4. Keeping things symmetric with both-edges
  5. Caveats
  6. Browser Support
  7. In Summary

~

# Classic vs. Overlay Scrollbars

Before we jump in, there’s a distinction between two types of scrollbars that we need to make.

# Overlay Scrollbars

Overlay Scrollbars are those iOS/macOS-style scrollbars which are placed over the content. They are not shown by default, but only while the user is scrolling. To keep the content underneath visible they are semi-transparent, but that’s totally up to the user-agent (browser) to determine. While interacting with them, their size may also vary.


Figure: An Overlay Scrollbar is placed over the content.

# Classic Scrollbars

Classic Scrollbars are scrollbars that are placed in the so-called “Scrollbar Gutter”. The Scrollbar Gutter is the space between the inner border edge and the outer padding edge. With classic scrollbars, the size of the Scrollbar Gutter is the same as the width of the scrollbar. These scrollbars are usually opaque (not transparent) and take away some space from the adjacent content.


Figure: A Classic Scrollbar takes away some space from the adjacent content.

🍏 macOS User? You can switch from Overlay to Classic Scrollbars via System Preferences!

If you’re a macOS user you can switch from Overlay to Classic Scrollbars via System Preferences → General. Set “Show scroll bars” to “Always”:

Using defaults you can also enable it:

defaults write NSGlobalDomain AppleShowScrollBars -string "Always"

Some applications — such as Chrome — need to be restarted after changing the setting.

~

# The Problem

When the content of a box becomes too big (e.g. when it is overflowing), the browser will — by default — show a scrollbar. In case of a classic scrollbar this has a nasty side-effect: as the scrollbar needs some space, the available width for the content shrinks — thus the layout shifts.


Figure: As the scrollbar gets shown, the content shifts.

☝️ In case of Overlay Scrollbars there’s no layout shift, as those scrollbars get rendered over the content.

~

# The Solution: scrollbar-gutter: stable;

The scrollbar-gutter property aims to solve the problem described above.

By setting scrollbar-gutter to stable we can have the UA always show the Scrollbar Gutter, even if the box is not overflowing and no scrollbar is shown. This way we have a visually stable layout: when the box starts to overflow the scrollbar will be rendered but no layout shift will happen as space for it was already reserved.


Figure: As the scrollbar gets shown, the content does not shift as the browser had already reserved space for the scrollbar gutter.

When the scrollbar gutter is present but the scrollbar is not, the background of the scrollbar gutter is painted as an extension of the padding.

Note that this scrollbar-gutter property has no effect on the rendering of the scrollbar itself — it only affects the rendering of the gutter. The rendering of the scrollbar is controlled by the overflow property.

The default value for scrollbar-gutter is auto. With this value set, the behavior is unchanged from the one described in The Problem

~

# Keeping things symmetric with both-edges

A scrollbar-gutter value of stable can be extended with both-edges. By setting scrollbar-gutter: stable both-edges; you can achieve symmetry. As per spec:

If a scrollbar gutter would be present on one of the inline start edge or the inline end edge of the box, another scrollbar gutter must be present on the opposite edge as well.


Figure: As the scrollbar gets shown, the content does not shift. Above that the same gutter space was reserved on the opposite edge.

In a previous version of the spec both-edges was named mirror.

~

# Caveats

There are only two small caveats with this one:

  1. As for the overflow property, a scrollbar-gutter set on the root element is applied to the viewport instead.
  2. Unlike the overflow property, the browser will not propagate scrollbar-gutter from the HTML body element.

~

# Browser Support

scrollbar-gutter is not supported in any browser at the time of writing. Chromium has released an “Intent To Ship” just last week, so I expect it to land in Chromium unflagged pretty soon. Other browser vendors are sending positive signals towards this addition, so they’ll follow too.

To follow along, here are the relevant Tracking Bugs:

~

# In Summary

With the scrollbar-gutter we can prevent some unwanted layout changes caused by scrollbars. The graphic below summarizes the scenarios covered in this post:

If your browser supports scrollbar-gutter, you can also check out this CodePen demo:

See the Pen CSS scrollbar-gutter demo by Bramus (@bramus) on CodePen.

~

To help spread the contents of this post, feel free to retweet the announcement tweet:

~

🔥 Like what you see? Want to stay in the loop? Here's how:

About the author

Bramus is a Freelance Web Developer from Belgium. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Join the Conversation

6 Comments

Leave a comment

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.