DEV Community

Cover image for scrollbar-gutter to the rescue
Davor Hrg
Davor Hrg

Posted on

scrollbar-gutter to the rescue

As of 2026, scrollbar customization has reached a high level of cross-browser stability through standard CSS properties, specifically addressing preventing content width changes (layout shifts).

Of series of #stealbackfromai

Preventing Content Width Changes

The most effective way to ensure a scrollbar does not change content width is the scrollbar-gutter property, which is now widely supported in modern browsers.

  • scrollbar-gutter: stable;: This reserves space for the scrollbar even when content doesn't overflow. This prevents the "jumping" effect where content shifts left once a scrollbar appears.
  • Integrating with Padding: When no scrollbar is present, the reserved gutter is painted as an extension of your existing padding. This allows you to define a consistent layout where the scrollbar simply "fills in" the space you've already allocated.
  • Centering Content: You can use scrollbar-gutter: stable both-edges; to reserve space on both sides of a container, keeping centered content perfectly aligned regardless of scroll state.

Floating/Overlay Behavior

"floating" scrollbars are typically handled as overlay scrollbars by the operating system (standard on macOS and mobile).

  • Native Overlay: If the OS uses overlay scrollbars, they naturally float on top of content without affecting layout width.
  • Standard Styling: You can now use standard properties like scrollbar-width (values: auto, thin, none) and scrollbar-color to adjust look and feel across Chrome, Firefox, and Safari without relying solely on old -webkit- prefixes.

Implementation Summary

To achieve a look where the scrollbar doesn't shift content and fits within your padding:

.container {
  overflow-y: auto;
  /* Reserves the space so content width stays fixed */
  scrollbar-gutter: stable;
  /* Modern styling for the scrollbar itself */
  scrollbar-width: thin;
  scrollbar-color: #888 transparent; 
}
Enter fullscreen mode Exit fullscreen mode

To implement a layout where the scrollbar occupies the "padding" area without shifting content, you can combine

scrollbar-gutter: stable with CSS variables to dynamically manage your container's internal spacing.

Modern Implementation with CSS Variables

This approach uses a variable for padding that accounts for the scrollbar space, ensuring your content remains visually centered or aligned as if the scrollbar were "floating" in that reserved gutter.

:root {
  /* Define base padding for your layout */
  --site-padding: 2rem;
  /* Use a variable for scrollbar color for easy theme switching */
  --sb-thumb: #888;
  --sb-track: transparent;
}

.scroll-container {
  /* 1. Layout Stability */
  overflow-y: auto;
  /* Always reserves space for the scrollbar so content doesn't jump */
  scrollbar-gutter: stable; 

  /* 2. Visual Customization (2026 Standards) */
  scrollbar-width: thin; /* Options: auto, thin, none */
  scrollbar-color: var(--sb-thumb) var(--sb-track);

  /* 3. Padding Integration */
  /* Content is padded by --site-padding, and the gutter 
     sits alongside it without pushing the content in further */
  padding-inline: var(--site-padding);

  /* Optional: Mirror the gutter on the left for perfect centering */
  /* scrollbar-gutter: stable both-edges; */
}

/* Hover effect to make the "floating" bar more interactive */
.scroll-container:hover {
  --sb-thumb: #555;
}
Enter fullscreen mode Exit fullscreen mode

demos

  • CodePen by Connum Comprehensive Toggle Demo: This allows you to toggle scrollbar-gutter: stable and both-edges on and off to see exactly how it prevents layout shifts.
  • CodePen by waxolunist Centered Content Demo: This shows how to use stable both-edges to keep content perfectly centered within its padding, even when a scrollbar is added.
  • interactive demo on Defensive CSS shows how this works with your padding specifically, which focuses on using this property to keep UI "polished" and prevent content from bumping into the scrollbar.

Recap

In these examples, the magic happens with these three lines:

.container {
  overflow-y: auto;          /* Only show scrollbar if needed */
  scrollbar-gutter: stable;  /* Reserve the space to prevent width change */
  padding: 20px;             /* Scrollbar sits in its gutter, NOT on your padding */
}
Enter fullscreen mode Exit fullscreen mode

how does this compare to scroll: always

While overflow-y: scroll (always) and scrollbar-gutter: stable both prevent layout shifts, they differ significantly in visual "clutter" and how they handle different operating systems.

Comparison Table

Feature overflow-y: scroll scrollbar-gutter: stable
Visibility Always shows the scrollbar track and thumb, even if content doesn't overflow. Only shows the thumb when content overflows, but always reserves the space.
Visual Look Can look "broken" or cluttered on short pages due to the empty track. Keeps the layout clean; the reserved space is invisible (matches background) until needed.
Layout Shift Prevents shifts because the scrollbar is permanent. Prevents shifts by "locking" the content width regardless of overflow state.
Overlay SB Forces a gutter even on systems that use floating/overlay scrollbars (like macOS). Smart: On overlay systems, it reserves zero space because the scrollbar floats on top anyway.

The main drawback of the old overflow-y: scroll trick is that it forces an "ugly" empty scrollbar track on every page.

With scrollbar-gutter: stable, the browser reserves the exact width of a scrollbar as a "blank" gutter.

  1. When content is short: You see your background color in that gutter, but no scrollbar track.
  2. When content overflows: The scrollbar thumb simply appears in that reserved space.
  3. With Overlay Scrollbars: It does nothing on mobile or macOS (where scrollbars don't take up space), whereas overflow: scroll might force an unnecessary layout change

Reset

Many modern "resets" now use this combination for a polished feel:

html {
  /* Only scroll if needed */
  overflow-y: auto; 
  /* Fallback for older Safari versions */
  overflow-y: scroll; 
  /* Modern standard to prevent jumping */
  scrollbar-gutter: stable; 
}
Enter fullscreen mode Exit fullscreen mode

More

Top comments (0)