Articles

CSS Scrollbar Styling: scrollbar-color and scrollbar-width

CSS now styles scrollbars natively with scrollbar-color and scrollbar-width, replacing years of vendor-prefixed hacks. Here's how they work.

Takina Takina · · 3 min read
Close-up of CSS code on a screen

Scrollbar styling in CSS lets you control the color and thickness of a scroll container’s scrollbar directly, using the scrollbar-color and scrollbar-width properties, without touching the browser’s default track-and-thumb rendering pipeline through hacks or images. It replaced a long era of non-standard, vendor-specific pseudo-elements that worked differently — or not at all — across browsers.

The two standard properties

scrollbar-width controls thickness. It takes one of three keywords:

.scroll-box {
  scrollbar-width: auto;   /* default, platform-native width */
  scrollbar-width: thin;   /* a narrower scrollbar */
  scrollbar-width: none;   /* hides it, but scrolling still works */
}

scrollbar-color sets the thumb and track colors as a space-separated pair:

.scroll-box {
  scrollbar-color: #6366f1 #e5e7eb; /* thumb-color track-color */
}

Set to auto, the browser uses its platform default. There’s no separate hover or active state property — browsers apply their own subtle hover feedback automatically on top of whatever base colors you set.

Why this replaced the old approach

Before these properties shipped broadly, styling a scrollbar meant reaching for ::-webkit-scrollbar and its related pseudo-elements (::-webkit-scrollbar-thumb, ::-webkit-scrollbar-track, and so on) — a WebKit-specific extension that Chromium-based browsers also adopted. It worked, but it wasn’t standardized: Firefox never implemented it, so any site relying on it needed a completely separate fallback (or no styling at all) for non-Chromium browsers. It also required a fair amount of boilerplate for something conceptually simple — setting a color and a width.

scrollbar-color and scrollbar-width are standard CSS properties supported across modern engines, so the same two lines work everywhere without a fallback branch. The tradeoff is control: the ::-webkit-scrollbar family let you style corner pieces, buttons, and apply gradients or border-radius to the thumb, which the standard properties don’t expose. For most UI needs — a subtler scrollbar that matches your color scheme instead of the OS default — the standard properties are enough.

Using custom properties for theming

Because scrollbar-color takes plain color values, it composes naturally with CSS custom properties and dark-mode variables:

:root {
  --scrollbar-thumb: #94a3b8;
  --scrollbar-track: transparent;
}

@media (prefers-color-scheme: dark) {
  :root {
    --scrollbar-thumb: #475569;
  }
}

* {
  scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
  scrollbar-width: thin;
}

Applying it globally on * (or html) is the common pattern, since scrollbars can appear on any scrollable element, not just the document itself — long code blocks, modal bodies, and sidebar navs all pick up the same theme automatically.

Scrollbar-gutter: reserving space to avoid layout shift

A related property, scrollbar-gutter, addresses a different but adjacent problem: on desktop browsers where scrollbars take up layout space, content can shift horizontally the instant a scrollbar appears or disappears (for example, when a modal opens and the body becomes non-scrollable). Setting scrollbar-gutter: stable reserves the scrollbar’s space permanently, even when there’s nothing to scroll yet, so the layout doesn’t jump:

html {
  scrollbar-gutter: stable;
}

This matters most in Core Web Vitals terms for pages where content height changes dynamically — infinite scroll feeds, expandable accordions — since an appearing scrollbar can register as a layout shift.

Hiding scrollbars without breaking scrolling

scrollbar-width: none hides the scrollbar visually while keeping the element scrollable by touch, mouse wheel, or keyboard. This is common in horizontally scrolling carousels or tab strips where a visible scrollbar would look out of place. It’s worth pairing with a visible affordance — like a partial next item peeking into view, or explicit next/previous buttons — so the ability to scroll isn’t hidden along with the scrollbar. Relying purely on overflow combined with a hidden scrollbar (see CSS overflow) is fine functionally, but accessibility guidance still favors giving users some visual cue that more content exists.

Browser support and fallback behavior

Both properties degrade gracefully: a browser that doesn’t recognize scrollbar-color simply ignores the declaration and falls back to its native scrollbar rendering. There’s no need for @supports guards or JavaScript feature detection — worst case, older browsers just show the default scrollbar instead of your themed one, which was already the pre-CSS-styling behavior.

The takeaway

scrollbar-color and scrollbar-width give you cross-browser scrollbar theming in two lines of standard CSS, covering thumb color, track color, and thickness without vendor prefixes. For finer visual control — rounded thumbs, gradients, custom buttons — the older ::-webkit-scrollbar pseudo-elements are still there as a Chromium-only enhancement layer, but the standard properties should be your default starting point.

Takina Takina · · 4 min read

CSS field-sizing Property Explained

The CSS field-sizing property lets form controls like textareas grow to fit their content automatically, without JavaScript resize listeners.

#CSS #Web Development #Frontend
Takina Takina · · 4 min read

The CSS color-scheme Property, Explained

CSS color-scheme tells the browser which themes a page supports so native form controls, scrollbars, and UI render in dark mode without extra CSS.

#CSS #Web Development #Frontend