Users who enable high-contrast modes in their operating system or browser expect UI elements (like scrollbars) to be extremely legible, often relying on stark foreground-background separation rather than subtle grays or theme colors.
This guide provides optional instructions on how to use the @media (prefers-contrast: more) CSS media feature to enforce high-contrast scrollbar styling.
Enhance Legibility
When customizing scrollbars with scrollbar-color or custom variables, you can provide an explicit override for high-contrast modes. This is especially helpful if your primary application theme uses low-contrast scrollbars for aesthetic reasons.
OPTIONAL: Use a @media (prefers-contrast: more) block to define dark, distinct colors for the thumb and track.
/* Define default standard colors as variables */
.scroller {
--scrollbar-thumb: #bbb;
--scrollbar-track: #f1f1f1;
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
scrollbar-width: thin;
scrollbar-gutter: stable;
}
/* OPTIONAL: Provide clear, high-contrast overrides */
@media (prefers-contrast: more) {
.scroller {
/* Use extremely distinct colors like solid black against white */
--scrollbar-thumb: #000000;
--scrollbar-track: #ffffff;
}
}
Issues to be aware of when using scrollbar-color
- Do NOT animate or transition
scrollbar-color. A WebKit bug causes the scrollbar to flicker every timescrollbar-colorchanges. - On macOS,
scrollbar-color(standard) and::-webkit-scrollbar(legacy) properties are ignored by default because macOS uses native "overlay" scrollbars. You MUST pair custom colors withscrollbar-width(e.g.,thinorauto) to force macOS to render them. - Even with
scrollbar-widthapplied, macOS overlay scrollbars render the track (gutter) as transparent by default. If the design requires a visible track background color on MacOS, you MUST applyscrollbar-gutter: stable;to the scrollable container, but note that it only appears after the user hovers over the scrollbar. - Even with
scrollbar-gutter: stablethe track may be transparent on MacOS. The thumb should not depend on the track color to be visible.
Fallbacks & Browser Support
Fallbacks & browser support for scrollbar-color
This feature is progressive enhancement and does not always require fallbacks.
If the styling is important and the user's Baseline target is "Baseline Widely Available" or earlier, you SHOULD include the non-standard ::-webkit-scrollbar pseudo-elements as fallbacks.
Wrap legacy fallbacks in an @supports not (scrollbar-color: auto) block to prevent conflicts between standard properties and legacy WebKit selectors in browsers that support both natively.
If you are using custom properties to define colors, these will cascade to the legacy WebKit selectors automatically. You do NOT need to duplicate them.
/* Legacy fallback for WebKit/Blink browsers */
@supports not (scrollbar-color: auto) {
.scroller::-webkit-scrollbar {
/* Must define base size in WebKit for custom colors to be visual */
width: 12px;
height: 12px;
}
.scroller::-webkit-scrollbar-thumb {
background: var(--scrollbar-thumb);
}
.scroller::-webkit-scrollbar-track {
background: var(--scrollbar-track);
}
}