Scroll this area to see your custom scrollbar in action. Adjust the controls on the left to change the width, color, radius and opacity of the scrollbar thumb and track.

CSS scrollbars are styled using two APIs: the WebKit pseudo-element approach (::-webkit-scrollbar) for Chrome, Edge, and Safari, and the W3C standard scrollbar-color and scrollbar-width properties for Firefox.

Both APIs are output below — copy both blocks and include them in your stylesheet for maximum cross-browser coverage.

Thin scrollbars with subtle colors are best for most UIs. Wider scrollbars improve accessibility — WCAG recommends interactive targets be at least 24px.

Mobile browsers generally ignore custom scrollbar styles. This is primarily a desktop feature.

On macOS, scrollbars are hidden by default and only appear on scroll. On Windows they always take up layout space.

Keep scrolling to test behaviour through the full scroll range.

Generated CSS

CSS Scrollbar Styling — Complete Reference

Browser scrollbars are one of the most consistently ugly default UI elements on the web, and they vary dramatically between operating systems. On Windows, they appear as wide, flat grey bars that consume layout space even when unused. On macOS, they're narrow and only appear while scrolling. On Linux, they vary by desktop environment and GTK theme. CSS scrollbar styling lets you override these defaults to create scrollbars that match your design system — or to hide them entirely while keeping the content scrollable.

Two competing APIs you must know

There are currently two separate CSS specifications for scrollbar styling, supported by different browsers. The WebKit pseudo-element API uses a family of ::-webkit-scrollbar pseudo-elements and works in Chrome, Edge, and Safari. It gives you precise control over every aspect of the scrollbar's appearance. The W3C CSS Scrollbars Level 1 specification uses scrollbar-color and scrollbar-width properties and is the standards-track approach — Firefox has supported it since version 64, and Chrome and Edge adopted it starting at version 121.

Because the two APIs have overlapping but not identical browser coverage, the correct approach for production code is to include both. The W3C properties act as the authoritative declaration in Firefox, and the WebKit pseudo-elements apply in Chromium-based browsers and Safari. When both are present, each browser uses only what it understands and ignores the other.

The WebKit pseudo-element family

The WebKit approach works by exposing the scrollbar's sub-components as styleable pseudo-elements. The ::-webkit-scrollbar pseudo-element targets the full scrollbar track and is where you set the width (for vertical scrollbars) and height (for horizontal scrollbars). Removing the default arrow buttons — which most modern designs do — requires setting ::-webkit-scrollbar-button { display: none; }. The ::-webkit-scrollbar-thumb pseudo-element styles the draggable handle. The ::-webkit-scrollbar-track styles the track area behind the thumb. The ::-webkit-scrollbar-corner styles the small square where a vertical and horizontal scrollbar meet — commonly set to match the track color.

One important nuance: for WebKit scrollbar styling to apply to an element, that element must actually have a scrollbar. The element needs overflow: auto or overflow: scroll and content that overflows its dimensions. Without those, the pseudo-elements match nothing. Additionally, setting ::-webkit-scrollbar { width: 0 } hides the scrollbar completely while keeping the content scrollable — though using scrollbar-width: none is the cleaner cross-browser approach for this case.

The W3C scrollbar-color property

The scrollbar-color property takes exactly two color values: the thumb color first, then the track color. It does not accept gradients, transparency on some browsers may not work as expected, and you cannot control hover states or border-radius. What it lacks in control it makes up for in simplicity and standards compliance. For simple recoloring — like making a dark-mode scrollbar on a dark background — it's the most concise solution. For anything more decorative, the WebKit approach is necessary.

The scrollbar-width property

The scrollbar-width property accepts three values. auto uses the platform default, which is typically around 15-17px on Windows and 8px on macOS. thin produces a narrower scrollbar, approximately 8px in most implementations. none hides the scrollbar entirely while keeping the content scrollable — the element still responds to mouse wheel, keyboard, and touch scroll events, but no visible scrollbar appears. Note that scrollbar-width: none does not disable scrolling — for that you need overflow: hidden.

Scoping scrollbar styles

Scrollbar styles declared without a scope selector apply globally to all scrollable elements on the page, including the document's main scrollbar. To scope a style to a specific element — like a code block or a sidebar nav — prepend the element's selector to the pseudo-element: .code-block::-webkit-scrollbar { width: 4px; }. This is particularly useful when you want a subtle custom scrollbar on nested scrollable containers while leaving the main page scrollbar at its default size.

Horizontal scrollbar styling

Horizontal scrollbars use height instead of width on the ::-webkit-scrollbar pseudo-element. Everything else works identically to vertical scrollbars. Horizontal scrolling containers typically need overflow-x: auto; overflow-y: hidden; white-space: nowrap or equivalent to prevent content from wrapping. A common pattern is a horizontally scrolling tag list or code block with a 4-5px custom scrollbar at the bottom.

Designing scrollbars for accessibility

The most important accessibility consideration is scrollbar visibility and size. Very thin scrollbars — 2-3px wide — can be nearly invisible and hard to grab with a mouse, particularly for users with motor impairments. WCAG 2.1 Success Criterion 2.5.5 recommends interactive targets be at least 44×44 CSS pixels, though for scrollbars, 8-10px is generally considered the minimum practical width. For applications with intensive scrolling — data tables, code editors, document viewers — err toward wider scrollbars. The hidden scrollbar pattern (scrollbar-width: none) should be used only when an alternative scroll mechanism exists (like arrow buttons or swipe gestures) or when the scrollable content is brief enough that users can always see its full extent.

macOS vs Windows behaviour

macOS hides scrollbars by default and shows them as an overlay only during active scrolling. This means the scrollbar does not take up layout space, and the custom styles only appear transiently. On Windows, the traditional scrollbar occupies permanent layout space alongside the content — your custom width is always visible and affects the content area. This difference has real consequences for layout: an element styled at exactly 300px wide on macOS will have 300px of content; on Windows with a 10px scrollbar, only 290px of content width is available. Use scrollbar-gutter: stable to reserve layout space for the scrollbar on macOS even when it's not visible, eliminating layout shifts when scroll behaviour changes.

Mobile scrollbar behaviour

iOS Safari and Android Chrome handle scrollbars as overlays that appear briefly during scroll and then fade out. Custom scrollbar CSS has essentially no effect on mobile — the platform renders its own scroll indicator overlay regardless of your CSS. This is by design: mobile touch interfaces don't need draggable scrollbars because scrolling is done by finger gestures directly on the content. Custom scrollbar styling is therefore a purely desktop enhancement that degrades gracefully to the platform default on mobile.

Using CSS variables for themed scrollbars

One of the most practical applications of custom scrollbars is integrating them into a design system's theme. By using CSS custom properties for the thumb and track colors, you get automatic dark and light mode switching with no JavaScript. Define the scrollbar colors as CSS variables alongside your other theme tokens, and the scrollbar recolors automatically whenever the theme class or prefers-color-scheme media query switches the variable values. This keeps your scrollbar styling in sync with the rest of your design system without any additional maintenance.

Do custom scrollbars work in Firefox?

Firefox supports the scrollbar-color and scrollbar-width properties since version 64, which covers all currently supported Firefox versions. It does not support the ::-webkit-scrollbar pseudo-elements. For Firefox coverage, always include both the W3C properties alongside the WebKit pseudo-elements — Firefox will use what it understands and ignore the rest.

Why doesn't my ::-webkit-scrollbar style work?

The element must have a scrollbar to style. Check that the element has overflow: auto or overflow: scroll and that the content actually overflows the element's dimensions. Also check that you're not styling the pseudo-element on an element whose scrollbar is provided by the document body — for the main page scrollbar, apply the styles to the html or body element, or use a global selector.

Can I use gradients for scrollbar-color?

The scrollbar-color property accepts only two solid color values. Gradients are not supported in the W3C specification. Gradient thumbs are possible using ::-webkit-scrollbar-thumb { background: linear-gradient(...) } in WebKit browsers only, so they'll apply in Chrome, Edge, and Safari but not Firefox.

How do I hide the scrollbar on a mobile-style container?

Use scrollbar-width: none for Firefox and ::-webkit-scrollbar { display: none } for WebKit browsers. Also add -ms-overflow-style: none for legacy IE and Edge support. The element remains scrollable — all scroll events, wheel events, and touch events still work normally. Only the visual scrollbar track and thumb are hidden.

What is scrollbar-gutter and when should I use it?

scrollbar-gutter controls whether layout space is reserved for the scrollbar even when it's not visible. The value stable reserves the space permanently, preventing the layout from shifting when content changes cause a scrollbar to appear or disappear. The value stable both-edges reserves space on both sides for balance. This is particularly useful for centered layouts where a scrollbar appearing on the right side would shift the content left.

Tool last updated: