CSS Scrollbar Styling
Styling scrollbars with CSS is not yet fully standardized.
However, browsers like Chrome, Edge, and Safari—collectively known as [Webkit-based browsers]—provide their own methods for styling scrollbars using CSS.
Additionally, [Firefox and Webkit-based browsers such as Chrome and Edge] can also style scrollbars using CSS based on experimental, non-standard implementations referenced by the W3C. This guide explains both approaches separately.
We will examine CSS scrollbar styling separately for [Webkit-based browsers] and [Firefox along with Chrome and Edge].
Chrome and Edge
are Webkit-based browsers, but they are also included in the approach that follows Firefox, using experimental, non-standard W3C-based CSS.
Therefore, these browsers are included in both methods described below.
The following outline will guide the explanations:
Be sure to carefully check browser compatibility for each approach.
CSS Scrollbar Styling for [Webkit-Based Browsers]
Before diving into the details, let's list the major Webkit-based browsers:
- Chrome (including Android WebView)
- Edge
- Safari (including iOS browsers)
- Samsung Internet
- Opera
Most major browsers, except for Firefox, are Webkit-based.
😃 Styling scrollbars for Webkit-based browsers essentially means custom-styling the scrollbars in almost all browsers except Firefox.
CSS Scrollbar Selectors
To style scrollbars in Webkit-based browsers, you need to understand the pseudo-element selectors provided by these browsers. The following are the four most commonly used pseudo-element selectors:
::-webkit-scrollbar |
The entire scrollbar. |
|---|---|
::-webkit-scrollbar-track |
The scrollbar track (the progress bar area), typically the portion with a gray bar over a white background. |
::-webkit-scrollbar-thumb |
The draggable scrollbar handle. |
::-webkit-scrollbar-button |
The arrow-shaped buttons on the scrollbar. |
Here's a helpful diagram:
Browser Compatibility Notes
Safari on iOS 13 (Mobile Safari) does not support custom styling for any scrollbar pseudo-element selectors except for ::-webkit-scrollbar with display: none.
Examples
Let's explore various examples of CSS scrollbar styling for Webkit-based browsers.
<div class="container">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
In sagittis purus sit amet felis aliquam, at aliquam odio consequat.
Morbi id faucibus turpis. Aenean risus mi,
euismod vitae pulvinar vitae, ultricies vel dolor.
Vivamus ac condimentum urna, sed condimentum orci.
Mauris sed elit in lectus iaculis elementum id eget ante.
Maecenas vulputate feugiat arcu, eu accumsan nisl pharetra eget.
Vestibulum bibendum vehicula risus sed elementum.
Duis porttitor sapien ut justo ultrices, vitae sollicitudin arcu lacinia.
Aliquam volutpat elit non dui luctus efficitur.
</div>
Basic Styling
.container {
padding: 0 0.5em;
max-width: 360px;
height: 150px;
overflow: auto;
}
.container::-webkit-scrollbar {
width: 10px;
}
.container::-webkit-scrollbar-track {
background-color: gray;
}
.container::-webkit-scrollbar-thumb {
background-color: skyblue;
}
.container::-webkit-scrollbar-button {
display: none;
}
This example demonstrates the most common scrollbar styling. The arrow buttons (::-webkit-scrollbar-button) are hidden using display: none.
Adding Hover Effects
.container {
padding: 0 0.5em;
max-width: 360px;
height: 150px;
overflow: auto;
}
.container::-webkit-scrollbar {
width: 10px;
}
.container::-webkit-scrollbar-track {
background-color: gray;
}
.container::-webkit-scrollbar-thumb {
background-color: skyblue;
}
.container::-webkit-scrollbar-button {
display: none;
}
/* Adding Hover Effects */
.container::-webkit-scrollbar-thumb:hover {
background-color: blue;
transition: all 0.2s; /* Note: This will not work */
}
This example adds a hover effect to the commonly styled scrollbar.
Note:
transition and animation properties do not work on scrollbar pseudo-elements in Webkit-based browsers.
Adding Rounded Corners
.container {
padding: 0 0.5em;
max-width: 360px;
height: 150px;
overflow: auto;
}
.container::-webkit-scrollbar {
width: 10px;
}
.container::-webkit-scrollbar-track {
background-color: gray;
}
.container::-webkit-scrollbar-thumb {
background-color: skyblue;
}
.container::-webkit-scrollbar-button {
display: none;
}
/* Adding Hover Effects */
.container::-webkit-scrollbar-thumb:hover {
background-color: blue;
transition: all 0.2s; /* Note: This will not work */
}
/* Adding Rounded Corners */
.container::-webkit-scrollbar-track,
.container::-webkit-scrollbar-thumb {
border-radius: 5px;
}
Not Working Warning
If you do not style the ::-webkit-scrollbar pseudo-element, none of the other scrollbar pseudo-elements or custom styling will work. The browser will apply its default scrollbar styles.
The ::-webkit-scrollbar pseudo-element is the primary selector that determines whether custom scrollbar styling is applied. To style scrollbars in Webkit browsers, you must explicitly style ::-webkit-scrollbar.
.container {
padding: 0 0.5em;
max-width: 360px;
height: 150px;
overflow: auto;
}
/*
.container::-webkit-scrollbar {
width: 10px;
}
*/
.container::-webkit-scrollbar-track {
background-color: gray;
}
.container::-webkit-scrollbar-thumb {
background-color: skyblue;
}
.container::-webkit-scrollbar-button {
display: none;
}
Hiding the Scrollbar
On mobile apps, you may have seen scrollable content without a visible scrollbar. This is a common pattern on touch-based devices and is familiar to users.
Even if the scrollbar is hidden with CSS, scrolling functionality remains (as long as overflow: hidden is not applied).
Accessibility Consideration:
When hiding scrollbars, make sure users have enough visual cues (hints) to indicate that the content is scrollable. This approach should only be used on touch-based devices.
.container {
padding: 0 0.5em;
max-width: 360px;
height: 150px;
overflow: auto;
}
.container::-webkit-scrollbar {
display: none;
}
CSS Scrollbar Styling for [Firefox along with Chrome and Edge]
These CSS properties are collectively called CSS Scrollbars, and there are two main properties.
Firefox supports scrollbar-related CSS properties based on the experimental non-standard draft published by the W3C in August 2023: the CSS Scrollbars Styling Module Level 1.
🔊 Update Notice:
Chrome and Edge also support these properties starting from version 121 on both desktop and mobile.
CSS Scrollbars
There are two CSS properties to specify the color and thickness of scrollbars.
scrollbar-color |
Specifies the color of the scrollbar. |
|---|---|
scrollbar-width |
Specifies the thickness (width) of the scrollbar. |
selector {
scollbar-color: gray darkgray;
scollbar-width: thin;
}
Here's a helpful diagram:
scrollbar-color Property
The scrollbar-color property sets the color of the scrollbar. Let's look at its syntax and definition.
selector {
scrollbar-color: auto || [ <thumb color> <track color> ]
}
| Initial value | auto |
|---|---|
| Applies to | scrolling boxes |
| Inherited | no |
Values
auto |
Initial value. The browser's standard scrollbar colors are used. |
|---|---|
<thumb color> <track color> |
The first color applies to the scrollbar thumb (the draggable handle), and the second color applies to the scrollbar track. |
Example
<div class="container">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
In sagittis purus sit amet felis aliquam, at aliquam odio consequat.
Morbi id faucibus turpis. Aenean risus mi,
euismod vitae pulvinar vitae, ultricies vel dolor.
Vivamus ac condimentum urna, sed condimentum orci.
Mauris sed elit in lectus iaculis elementum id eget ante.
Maecenas vulputate feugiat arcu, eu accumsan nisl pharetra eget.
Vestibulum bibendum vehicula risus sed elementum.
Duis porttitor sapien ut justo ultrices, vitae sollicitudin arcu lacinia.
Aliquam volutpat elit non dui luctus efficitur.
</div>
.container {
padding: 0 0.5em;
max-width: 360px;
height: 150px;
overflow: auto;
scrollbar-color: skyblue gray;
}
scrollbar-width Property
The scrollbar-width property specifies the thickness (width) of the scrollbar. Let's examine its syntax and definition.
selector {
scrollbar-width: auto | thin | none
}
| Initial value | auto |
|---|---|
| Applies to | scrolling boxes |
| Inherited | no |
Values
auto |
Initial value. Uses the browser's standard scrollbar width. |
|---|---|
thin |
Thinner than the browser’s standard scrollbar width. |
none |
The scrollbar is not displayed, but the element remains scrollable. |
예제
<div class="container">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
In sagittis purus sit amet felis aliquam, at aliquam odio consequat.
Morbi id faucibus turpis. Aenean risus mi,
euismod vitae pulvinar vitae, ultricies vel dolor.
Vivamus ac condimentum urna, sed condimentum orci.
Mauris sed elit in lectus iaculis elementum id eget ante.
Maecenas vulputate feugiat arcu, eu accumsan nisl pharetra eget.
Vestibulum bibendum vehicula risus sed elementum.
Duis porttitor sapien ut justo ultrices, vitae sollicitudin arcu lacinia.
Aliquam volutpat elit non dui luctus efficitur.
</div>
.container {
padding: 0 0.5em;
max-width: 360px;
height: 150px;
overflow: auto;
scrollbar-width: thin;
}
To hide the scrollbar, use scrollbar-width: none. In this case, the scrollbar is not displayed, but the element remains scrollable.
selector {
scrollbar-width: none;
}
Using scrollbar-color and scrollbar-width Together
<div class="container">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
In sagittis purus sit amet felis aliquam, at aliquam odio consequat.
Morbi id faucibus turpis. Aenean risus mi,
euismod vitae pulvinar vitae, ultricies vel dolor.
Vivamus ac condimentum urna, sed condimentum orci.
Mauris sed elit in lectus iaculis elementum id eget ante.
Maecenas vulputate feugiat arcu, eu accumsan nisl pharetra eget.
Vestibulum bibendum vehicula risus sed elementum.
Duis porttitor sapien ut justo ultrices, vitae sollicitudin arcu lacinia.
Aliquam volutpat elit non dui luctus efficitur.
</div>
.container {
padding: 0 0.5em;
max-width: 360px;
height: 150px;
overflow: auto;
scrollbar-color: skyblue gray;
scrollbar-width: thin;
}
CSS Scrollbar Styling That Considers All Major Browsers
Custom CSS scrollbar styling that works across both WebKit-based browsers and Firefox has its limitations. The CSS properties used in Firefox only allow customizing the scrollbar's color and width, which means you cannot add rounded corners, and the scrollbar width can only be slightly thinner than the default. Therefore, you cannot achieve identical styling across WebKit browsers and Firefox. However, you can achieve similar styling as follows:
- Hiding scrollbars in both WebKit browsers and Firefox
- Thin scrollbars without rounded corners
The following two examples demonstrate these approaches.
.container {
padding: 0 0.5em;
max-width: 360px;
height: 150px;
overflow: auto;
scrollbar-width: none; /* Hide scrollbars in Firefox, Chrome, and Edge */
}
.container::-webkit-scrollbar {
display: none; /* Hide scrollbars in WebKit browsers */
}
.container {
padding: 0 0.5em;
max-width: 360px;
height: 150px;
overflow: auto;
/* Scrollbars in Firefox, Chrome, and Edge */
scrollbar-color: skyblue gray;
scrollbar-width: thin;
}
/* WebKit browser scrollbars */
.container::-webkit-scrollbar {
width: 10px;
}
.container::-webkit-scrollbar-track {
background-color: gray;
}
.container::-webkit-scrollbar-thumb {
background-color: skyblue;
}
.container::-webkit-scrollbar-button {
display: none;
}
Reserving Space for Scrollbars in Advance
You may have experienced situations where text suddenly shifts or jumps when a scrollbar appears due to changes in an element's dimensions.
By using the scrollbar-gutter property, you can reserve space for the scrollbar in advance, regardless of whether it actually appears. This prevents unwanted visual shifts when a scrollbar is dynamically added, as the reserved space keeps the content stable.
scrollbar-gutter not applied
Text shifts or jumps depending on scrollbar presence
scrollbar-gutter applied
No visual shifts regardless of scrollbar presence
Next, let's review this using a code example.
Note:
In the demo, the animations are used to simulate scrollbars dynamically and are not part of the actual code.
Setting scrollbar-gutter: stable ensures that when overflow is set to hidden, scroll, or auto, the scrollbar space (gutter) always exists—even if the content does not overflow.
Important: This property does not change whether the scrollbar itself is visible; it only controls the presence of the scrollbar space (gutter).
<div class="container">
Lorem Ipsum is simply dummy text of the printing and
typesetting industry. Lorem Ipsum has been
the industry's standard dummy text ever since the 1500s,
when an unknown printer...
</div>
.container {
width: 250px;
height: 200px;
border: 5px solid #663399;
background: rgba(255, 0, 200, .15);
overflow: auto;
scrollbar-gutter: stable;
}
By reserving space in advance, you prevent unwanted content shifts or jumps when scrollbars appear due to changes in an element's dimensions.
Browser compatibility
Last updated: 2025-11-20
| Desktop | ||||
|---|---|---|---|---|
|
Desktop Chrome
|
DesktopDesktop Edge
|
Desktop Firefox
|
Safari
|
|
::-webkit-scrollbar
|
2 | 79 | Not supported | 4 |
::-webkit-scrollbar-track
|
2 | 79 | Not supported | 4 |
::-webkit-scrollbar-thumb
|
2 | 79 | Not supported | 4 |
::-webkit-scrollbar-button
|
2 | 79 | Not supported | 4 |
scrollbar-color
|
121 | 121 | 64 | Not supported |
scrollbar-width
|
121 | 121 | 64 | 18.2 |
Last updated: 2025-11-20
| Mobile | |||
|---|---|---|---|
|
Mobile Chrome
|
Mobile Firefox
|
Safari
|
|
::-webkit-scrollbar
|
18 | Not supported | 13, only display: none |
::-webkit-scrollbar-track
|
18 | Not supported | Not supported |
::-webkit-scrollbar-thumb
|
18 | Not supported | Not supported |
::-webkit-scrollbar-button
|
8 | Not supported | Not supported |
scrollbar-color
|
121 | 64 | Not supported |
scrollbar-width
|
121 | 64 | 18.2 |