Scrollbar styling

Use the scrollbar-width and scrollbar-color properties to style scrollbars.

Introduction

From Chrome version 2 it's been possible to style scrollbars with the ::-webkit-scrollbar-* pseudo-elements. This approach works fine in Chrome and Safari, but was never standardized by the CSS Working Group.

What did get standardized are the scrollbar-width and scrollbar-color properties, part of the CSS Scrollbars Styling Module Level 1 Specification. These properties are supported as of Chrome 121.

Browser Support

  • Chrome: 121.
  • Edge: 121.
  • Firefox: 64.
  • Safari: not supported.

Source

Scrollbars 101

Anatomy of a scrollbar

At the minimum a scrollbar consists of a track and a thumb. The track is the area in which the thumb can move. The track represents the entire scroll distance. The thumb represents the current position within the scrollable region. As you scroll, it moves within the track. The thumb is often also draggable.

Scrollbars can have more parts than just the thumb and track, though. For example, a scrollbar could have one or more buttons to increment or decrement the scroll offset. The parts that make up a scrollbar are determined by the underlying operating system.

Illustration of the parts that make up a scrollbar.
Illustration of the parts that make up a scrollbar. The illustration on the left is a bare-minimum scrollbar with only a track and thumb. The one on the right also has buttons.

Classic and overlay scrollbars

Before looking at how to style scrollbars, it’s important to understand the distinction between two types of scrollbar.

Overlay scrollbars

Overlay scrollbars are floating scrollbars rendered on top of content underneath. They are not shown by default but only while you are actively scrolling. To keep the content underneath visible they are often semi-transparent, but that’s up to the operating system to decide. While interacting with them, their size may also vary.

Illustration of a browser with an overlay scrollbar.
Illustration of a browser with an overlay scrollbar. The scrollbar overlays the content; the thumb is partially transparent.

Classic scrollbars

Classic scrollbars are scrollbars that are placed in a dedicated scrollbar gutter. The scrollbar gutter is the space between the inner border edge and the outer padding edge. These scrollbars are usually opaque (not transparent) and take away some space from the adjacent content.

Illustration of a browser with a classic scrollbar.
Illustration of a browser with a classic scrollbar. The scrollbar is positioned next to the content in its own dedicated area; the available width of the content is shrunk in comparison to the available width when overlay scrollbars are used.

The scrollbar-color and scrollbar-width properties

Giving scrollbars color with scrollbar-color

The scrollbar-color property lets you change the color scheme of scrollbars. The property accepts two <color> values. The first <color> value determines the color of the thumb, and the second one the color to use for the track.

.scroller {
  scrollbar-color: hotpink blue;
}

When using an overlay scrollbar, the color of the track has no effect by default. However, upon hovering the scrollbar, the track will show.

Demo: Styling Scrollbars: scrollbar-color

To use the default rendering provided by the operating system, use auto as its value.

Changing the size of the scrollbar with scrollbar-width

The scrollbar-width property lets you choose a narrower scrollbar, or even to hide the scrollbar completely without affecting scrollability.

Accepted values are auto, thin, and none.

  • auto: The default scrollbar width as provided by the platform.
  • thin: A thin variant of scrollbar provided by the platform, or a custom scrollbar thinner than the default platform scrollbar.
  • none: Effectively hides the scrollbar. The element is still scrollable though.

It is not possible to use a <length> such as 16px as the value for scrollbar-width.

.scroller {
  scrollbar-width: thin;
}

When using an overlay scrollbar, the thumb only gets drawn while you are actively scrolling the scrollable area.

Demo: Styling Scrollbars: scrollbar-width

Supporting older browser versions

To cater for browser versions that don’t support scrollbar-color and scrollbar-width, it’s possible to use both the new scrollbar-* and ::-webkit-scrollbar-* properties.

.scroller {
    --scrollbar-color-thumb: hotpink;
    --scrollbar-color-track: blue;
    --scrollbar-width: thin;
    --scrollbar-width-legacy: 10px;
}

/* Modern browsers with `scrollbar-*` support */
@supports (scrollbar-width: auto) {
    .scroller {
        scrollbar-color: var(--scrollbar-color-thumb) var(--scrollbar-color-track);
        scrollbar-width: var(--scrollbar-width);
    }
}

/* Legacy browsers with `::-webkit-scrollbar-*` support */
@supports selector(::-webkit-scrollbar) {
    .scroller::-webkit-scrollbar-thumb {
        background: var(--scrollbar-color-thumb);
    }
    .scroller::-webkit-scrollbar-track {
        background: var(--scrollbar-color-track);
    }
    .scroller::-webkit-scrollbar {
        max-width: var(--scrollbar-width-legacy);
        max-height: var(--scrollbar-width-legacy);
    }
}
Demo: Styling Scrollbars using scrollbar-* with a fallback to ::-webkit-scrollbar-*

Note that when you set the width or height of ::-webkit-scrollbar, an overlay scrollbar is always displayed, effectively turning it into a classic scrollbar.

To keep the illusion, you can choose to only change the colors when hovering the scroller.

.scroller::-webkit-scrollbar-thumb {
    background: transparent;
}
.scroller::-webkit-scrollbar-track {
    background: transparent;
}
.scroller:hover::-webkit-scrollbar-thumb {
    background: var(--scrollbar-color-thumb);
}
.scroller:hover::-webkit-scrollbar-track {
    background: var(--scrollbar-color-track);
}

.scroller:hover {
    --fix: ; /* This custom property invalidates styles on hover, thereby enforcing a style recomputation. This is needed to work around a bug in Safari. */
}
Demo: Styling Scrollbars using scrollbar-* with a fallback to ::-webkit-scrollbar-*, only applying the ::-webkit-scrollbar-* colors on hover