BrowserUX Blog

Front-End Development

CSS 🧩 UX

CSS: Customize Scrollbars the Modern Way

CSS custom scrollbar

Scrollbars are rarely customized, even though they’re an integral part of the user interface. Depending on the browser, their appearance can vary greatly—sometimes overly visible, sometimes invisible, and often inconsistent with a site’s overall design.

Fortunately, it’s now possible to style them using native CSS, fully compatible with all modern browsers—no hacks or JavaScript required. This tip shows how to do it cleanly, combining accessibility, visual consistency, and easy maintenance.

For the rest of the article, values will be written using variables to make the code easier to understand:


:root {
    /* Background color of the scrollbar container */
    --ui-scrollbar: #eaeaea;
    /* Track color */
    --ui-scrollbar-track: #ddecf6;
    /* Thumb color */
    --ui-scrollbar-thumb: #0e93f0;
    /* Thumb color on hover */
    --ui-scrollbar-thumb-hover: #f05e0e;
    /* Width of the vertical scrollbar */
    --ui-scrollbar-vertical-width: 10px;
    /* Height of the horizontal scrollbar */
    --ui-scrollbar-horizontal-height: 10px;
}

1. The Standard Method with scrollbar-color and scrollbar-width

Currently, the standard properties scrollbar-color and scrollbar-width are supported by all modern browsers: Chrome, Edge, Firefox, Safari…

They allow for quick and simple customization of scrollbar colors and thickness—but with fairly limited styling options:


html {
    scrollbar-color: var(--ui-scrollbar-thumb) var(--ui-scrollbar-track);
    scrollbar-width: auto;
}
  • scrollbar-color: defines the color of the thumb (the draggable handle) and the track (the scrollbar track).
  • scrollbar-width: controls the scrollbar thickness (auto, thin, or none).

Accessibility

For visibility reasons, it’s not recommended to use scrollbar-width: thin or none. This can make the scrollbar hard to distinguish for users with low vision or those relying on assistive technologies.
Prefer scrollbar-width: auto, or use thin carefully in a well-controlled context.

2. Advanced Customization for WebKit/Blink Browsers

The ::-webkit-scrollbar-* pseudo-elements allow for detailed customization of scrollbars. They offer fine-grained control over each scrollbar component:

::-webkit-scrollbar targets the entire scrollbar. You can define its background color and its width or height:


::-webkit-scrollbar {
    background: var(--ui-scrollbar);
    height: var(--ui-scrollbar-horizontal-height);
    width: var(--ui-scrollbar-vertical-width);
}

::-webkit-scrollbar-button targets the scrollbar buttons (up/down or left/right arrows), which are often unnecessary or visually unappealing (but can be customized if needed):


::-webkit-scrollbar-button {
    display: none;
}

::-webkit-scrollbar-corner prevents the display of a visible background square where the horizontal and vertical scrollbars intersect:


::-webkit-scrollbar-corner {
    background: transparent;
}

::-webkit-scrollbar-track sets the background color of the track (the rail) on which the thumb moves:


::-webkit-scrollbar-track {
    background-color: var(--ui-scrollbar-track);
}

::-webkit-scrollbar-thumb sets the color of the thumb, with a hover variant to improve visibility or interaction. You can also add a border-radius for a smoother appearance:


::-webkit-scrollbar-thumb {
    background-color: var(--ui-scrollbar-thumb);
    border-radius: calc(var(--ui-scrollbar-vertical-width) / 2);
}
    
::-webkit-scrollbar-thumb:hover {
    background-color: var(--ui-scrollbar-thumb-hover);
}

Advantages:

  • Allows very detailed customization of each scrollbar component.
  • Complements the standard method on browsers that don’t yet support scrollbar-color and scrollbar-width.
  • No conflicts: each browser applies only what it understands.

⚠️ Issues:

  • If you declare the standard properties (scrollbar-color / scrollbar-width) globally, the ::-webkit-scrollbar-* styles will not be applied in recent WebKit/Blink browsers (Chrome > 120, Edge > 120, Safari > 18.1).
  • Conversely, if you don’t use the standard properties, you lose scrollbar customization in Firefox.

To keep customization working in Firefox while preserving advanced control in modern WebKit/Blink browsers, a small CSS hack is needed, and we’ll explore it in the next section.

3. Keep WebKit-Level Customization While Preserving the Standard Method in Firefox

If you want to use the ::-webkit-scrollbar-* pseudo-elements in recent WebKit/Blink browsers while maintaining the standard scrollbar-color and scrollbar-width method in Firefox, you can target Firefox specifically using @supports.


/* Styled scrollbars only in Firefox */
@supports (-moz-appearance: none) {
    html {
        scrollbar-color: var(--ui-scrollbar-thumb) var(--ui-scrollbar-track);
        scrollbar-width: auto;
    }
}
  • This rule is ignored by all browsers except Firefox.
  • This way, fine-grained customization using ::-webkit-scrollbar-* is preserved in Chrome, Safari, and Edge.
  • And you still get a consistent native style in Firefox, without rendering conflicts.

4. Final Code


:root {
    /* Background color of the scrollbar container */
    --ui-scrollbar: #eaeaea;
    /* Track color */
    --ui-scrollbar-track: #ddecf6;
    /* Thumb color */
    --ui-scrollbar-thumb: #0e93f0;
    /* Thumb hover color */
    --ui-scrollbar-thumb-hover: #f05e0e;
    /* Vertical scrollbar width */
    --ui-scrollbar-vertical-width: 10px;
    /* Horizontal scrollbar height */
    --ui-scrollbar-horizontal-height: 10px;
}

/**
 * Applies standard scrollbar styling only in Firefox, allowing more advanced 
 * customization with WebKit pseudo-elements in other modern browsers 
 * (Chrome, Safari, Edge). 
 * Without this block, `::-webkit-scrollbar` rules will be ignored in 
 * Chrome > 120, Edge > 120, and Safari > 18.1, because `scrollbar-color` 
 * overrides them if present globally.
 */

@supports (-moz-appearance: none) {
    html {
        scrollbar-color: var(--ui-scrollbar-thumb) var(--ui-scrollbar-track);
        scrollbar-width: auto;
    }
}

/**
 * WebKit scrollbar pseudo-elements used for advanced customization
 * in all modern non-Firefox browsers. These styles are now fully active because 
 * scrollbar-color is scoped to Firefox only.
 */

/**
 * Styles the native scrollbar.
 */

::-webkit-scrollbar {
    background: var(--ui-scrollbar);
    height: var(--ui-scrollbar-horizontal-height);
    width: var(--ui-scrollbar-vertical-width);
}

/**
 * Hides scrollbar buttons for a cleaner look.
 */

::-webkit-scrollbar-button {
    display: none;
}

/**
 * Styles the scrollbar track and thumb.
 */

::-webkit-scrollbar-track {
    background-color: var(--ui-scrollbar-track);
}

::-webkit-scrollbar-thumb {
    background-color: var(--ui-scrollbar-thumb);
    border-radius: calc(var(--ui-scrollbar-vertical-width) / 2);
}

::-webkit-scrollbar-thumb:hover {
    background-color: var(--ui-scrollbar-thumb-hover);
}

/**
 * Prevents a background color from appearing in the scrollbar corner 
 * (the intersection between horizontal and vertical scrollbars).
 */

::-webkit-scrollbar-corner {
    background: transparent;
}
Logo browserux.css

Find this tip in browserux.css, a base CSS file designed as a modern alternative to classic resets and Normalize.css, focused on user experience and accessibility. It provides accessible, consistent foundations tailored to today’s web practices: browserux.css

About

This blog was designed as a natural extension of the BrowserUX ecosystem projects.

Its goal is to provide complementary resources, focused tips, and detailed explanations around the technical choices, best practices, and accessibility principles that structure these tools.

Each article or tip sheds light on a specific aspect of modern front-end (CSS, accessibility, UX, performance…), with a clear intention: to explain the “why” behind each rule to encourage more thoughtful and sustainable integration in your projects.