CSS: Customize Scrollbars the Modern Way

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 thethumb
(the draggable handle) and thetrack
(the scrollbar track).scrollbar-width
: controls the scrollbar thickness (auto
,thin
, ornone
).
♿ 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
andscrollbar-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;
}

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.