Scrollbar-Aware 100vw with scrollbar-gutter: stable
Full-width elements without horizontal scrollbar overflow
Using 100vw on a desktop with a classic scrollbar always overflowed the page horizontally. The fix used to be JavaScript that measured the scrollbar and exposed its width as a custom property. CSS now solves this when the root commits to a stable scrollbar gutter.
const sbw = window .innerWidth - document .documentElement.clientWidth;document.documentElement .style.setProperty( '--scrollbar', sbw + 'px');window.addEventListener( 'resize', () => { const w = window .innerWidth - document .documentElement.clientWidth; document.documentElement .style.setProperty( '--scrollbar', w + 'px');});html { scrollbar-gutter: stable; }.full-bleed { width: 100vw; margin-inline: calc(50% - 50vw);}viewport units Browser Support
This feature is well established and works across many devices and browser versions. It has been available across browsers since 2017.
Safe to use without fallbacks.
No measurement script
No window.innerWidth versus documentElement.clientWidth subtraction. No resize listener to keep a --scrollbar custom property in sync.
Triggered by scrollbar-gutter
The browser only subtracts when the scrollbar (or its reserved gutter) is guaranteed to be visible. Set scrollbar-gutter: stable on the root, or use overflow-y: scroll, and 100vw adjusts.
Applies to every variant
All viewport units track this. vw, svw, lvw, dvw all subtract the vertical scrollbar. vh and its variants subtract a horizontal scrollbar when forced.
How it works
Set width: 100vw on an element with a classic vertical scrollbar present and you get a horizontal scrollbar. 100vw historically included the scrollbar in its width, so the element was always wider than the usable viewport. The workaround was JavaScript: subtract document.documentElement.clientWidth from window.innerWidth, expose the difference as a custom property, and use calc(100vw - var(--scrollbar)) everywhere.
Chrome now subtracts the scrollbar from viewport units when the root commits to reserving space for one. Add scrollbar-gutter: stable (or overflow-y: scroll) to the html element and 100vw becomes the width of the actual usable viewport. The same rule applies to vh with a horizontal scrollbar. The advantage of scrollbar-gutter over overflow-y: scroll: a scrollbar only draws when the page actually needs one.
