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;
}
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;
}
demos
-
CodePen by Connum Comprehensive Toggle Demo: This allows you to toggle
scrollbar-gutter: stableandboth-edgeson and off to see exactly how it prevents layout shifts. -
CodePen by waxolunist Centered Content Demo: This shows how to use
stable both-edgesto 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 */
}
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.
- When content is short: You see your background color in that gutter, but no scrollbar track.
- When content overflows: The scrollbar thumb simply appears in that reserved space.
-
With Overlay Scrollbars: It does nothing on mobile or macOS (where scrollbars don't take up space), whereas
overflow: scrollmight 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;
}
More
- caniuse scrollbar-gutter
- MDN Web Docs scrollbar-gutter
- CSS-Tricks Guide scrollbar-gutter
- Go Make Things Prevent scrollbar jump
Top comments (0)