
🎨 Custom scrollbar in CSS: from W3C standard to WebKit gradients
The default gray browser scrollbar works like a business card made on a free website builder: it gets the job done, but leaves a mediocre impression. It's especially noticeable when the entire site is pixel-perfect, fonts are carefully chosen, colors are polished, and then there's this angular bar sticking out from the Internet Explorer era on the right.
Developers often avoid the topic. Not because it's difficult, four lines of CSS solve the problem. Rather, myths get in the way: "only works in Chrome," "users won't notice," "it's a gimmick, not a production feature."
In reality, the W3C standard covers the basics with two properties, and WebKit pseudo-elements give you control over every detail, from rounding to gradients. I've compiled both approaches into one tutorial: from specification to production-ready cross-browser code you won't be embarrassed to put into production.
💡 Quick overview:
- Configure the scrollbar using
scrollbar-widthandscrollbar-color: two lines, full cross-browser compatibility, no prefixes. - Master
::-webkit-scrollbarand its descendants for fine-grained control of the track, thumb, and corners. - Build a cross-browser solution: the standard for Firefox, pseudo-elements for Chrome/Safari/Edge, no conflicts.
- Examine common mistakes: specificity, accessibility, missing buttons, mobile browser pitfalls.
Why style the scrollbar
The first and main argument is visual cohesion. Imagine a dark landing page with neon accents and a bright white scrollbar on the right. Or a light minimalist site where the scrollbar is the only element breaking the color palette. Technically not a bug, but it looks unfinished.
The second point is branding. A colored scrollbar becomes part of the visual language: a green thumb for a healthy meal delivery service, orange for a booking platform. A small detail that reinforces the association without additional banners and popups.
Third, attention management. A thin semi-transparent scrollbar doesn't steal focus from the content. On long landing pages, a narrow bar doesn't visually eat up precious width pixels, and on mobile layouts with side margins every pixel counts.
And the key point: this isn't a trick for geeks. The scrollbar-width and scrollbar-color properties are part of the CSS Scrollbars Styling Module Level 1 specification and are supported by all current browsers. According to Can I Use data from June 2026, standard property coverage exceeds 95% of users, the era of vendor prefixes for scrollbars is over.
Standard approach: scrollbar-width and scrollbar-color
The simplest and most reliable method. Two properties without prefixes, clear syntax, works in Firefox, Chrome, Edge and Safari.
Basic syntax
1 body { 2 scrollbar-width: thin; 3 scrollbar-color: #4a90d9 #f0f0f0; 4 }
The first value in scrollbar-color is the thumb color, the second is the track color. The scrollbar-width property accepts three values:
auto, standard width (around 17px on Windows, 15px on macOS with a mouse);thin, thin scrollbar (about 8px);none, hide the scrollbar completely (scrolling still works, but the user may not realize the content scrolls, use with caution).
Example for dark theme
1 html { 2 scrollbar-width: thin; 3 scrollbar-color: #555 #1e1e1e; 4 }
Result: a dark track matching the background color and a gray thumb. Nothing breaks the palette, two lines of code.
Standard limitations
The specification is intentionally minimalist: you can't set border radius, shadows, gradients, or hover effects. This is a compromise between customization and preserving usability, an overly non-standard scrollbar breaks the familiar interaction model. If the standard set isn't enough, connect WebKit pseudo-elements.
Fine-tuning through::-webkit-scrollbar
The ::-webkit-scrollbar-* pseudo-element set isn't part of the W3C standard, but is supported by WebKit and Blink browsers: Chrome, Edge, Safari, Opera, Brave, Arc. Coverage, according to Can I Use statistics, comprises the vast majority of desktop users.
Scrollbar architecture in WebKit
A browser scrollbar consists of seven parts, each with its own pseudo-element:
Pseudo-element | What it styles |
|---|---|
| The entire scrollbar (width, background) |
| The track (background strip) |
| Part of the track not occupied by the thumb |
| The thumb (draggable part) |
| Arrow buttons at the ends |
| Corner between horizontal and vertical scrollbars |
| Resizing element in the corner |
In practice, the vast majority of tasks are solved with three: scrollbar, track and thumb. The rest are for specific design solutions.
Example: neat scrollbar for a blog
1 ::-webkit-scrollbar { 2 width: 6px; 3 } 4 5 ::-webkit-scrollbar-track { 6 background: transparent; 7 } 8 9 ::-webkit-scrollbar-thumb { 10 background: #c1c1c1; 11 border-radius: 3px; 12 } 13 14 ::-webkit-scrollbar-thumb:hover { 15 background: #a0a0a0; 16 }
Six pixels wide, transparent track (invisible without scrolling), rounded thumb with darkening on hover. The scrollbar doesn't shout about itself, but looks modern.
Example with gradient for a landing page
1 ::-webkit-scrollbar { 2 width: 8px; 3 } 4 5 ::-webkit-scrollbar-track { 6 background: #1a1a2e; 7 border-radius: 4px; 8 } 9 10 ::-webkit-scrollbar-thumb { 11 background: linear-gradient(180deg, #e94560, #0f3460); 12 border-radius: 4px; 13 border: 1px solid #16213e; 14 } 15 16 ::-webkit-scrollbar-thumb:hover { 17 background: linear-gradient(180deg, #ff6b81, #1a508b); 18 }
Vertical gradient on the thumb, dark track, thin border to separate from the background. Three additional lines to the base, the page feels different.
Hiding the scrollbar without losing scroll
Classic technique for modal windows and burger menus:
1 .hide-scrollbar { 2 overflow-y: scroll; 3 scrollbar-width: none; 4 } 5 6 .hide-scrollbar::-webkit-scrollbar { 7 display: none; 8 }
The container remains scrollable, but the bar disappears both in Firefox (scrollbar-width: none) and in WebKit browsers (display: none on ::-webkit-scrollbar itself).
Cross-browser solution
Combine the standard and pseudo-elements into one block, coverage is nearly complete:
1 /* W3C standard — Firefox, modern Chrome/Edge/Safari */ 2 html { 3 scrollbar-width: thin; 4 scrollbar-color: #888 #f1f1f1; 5 } 6 7 /* WebKit pseudo-elements — detailed styling for Chrome/Safari/Edge */ 8 ::-webkit-scrollbar { 9 width: 8px; 10 } 11 12 ::-webkit-scrollbar-track { 13 background: #f1f1f1; 14 border-radius: 4px; 15 } 16 17 ::-webkit-scrollbar-thumb { 18 background: #888; 19 border-radius: 4px; 20 } 21 22 ::-webkit-scrollbar-thumb:hover { 23 background: #555; 24 }
Order matters: standard properties first, then pseudo-elements. Browsers with standard support apply scrollbar-color and ignore ::-webkit-scrollbar-*, as the specification requires. Browsers without standard support use pseudo-elements. No conflict arises.
Where to insert the code
Three options, from simple to flexible:
- Globally in the theme's
style.css.** Suitable if the scrollbar style is the same for the entire site. Downside: changes will be lost on theme update. - In the "Additional styles" section of the customizer. Path: Appearance → Customize → Additional styles. Safe method for WordPress: styles live in theme settings and don't reset on update.
- Through a plugin like Code Snippets. If you need to specifically set scrollbar for certain pages through CSS classes.
In a child theme, styles are connected through a separate file via wp_enqueue_scripts with the wp_head hook.
Common mistakes when styling
Forgotten cross-browser compatibility. Only set ::-webkit-scrollbar, default bar remains in Firefox. Always add scrollbar-width and scrollbar-color as a pair above in the code.
Scrollbar too thin. At 2-3px width in ::-webkit-scrollbar, clicking the thumb with the mouse becomes a motor skills task. Especially critical on laptops without an external mouse. Minimum comfortable width is 6px.
Zero contrast. Gray thumb on gray track merges into one blob. Minimum color contrast between thumb and track is 3:1, a WCAG 2.1 AA requirement for interface elements.
Overriding all pseudo-elements unnecessarily. Code bloats, zero effect. In most cases, scrollbar, track and thumb are enough. Touch buttons (button) and corner (corner) only if the design really requires it.
Style leakage onto entire body. Setting on * or html without restrictions styles internal scrollbars too: text fields, code blocks, dropdown lists. For code previews this is almost always unnecessary. Use class selectors: .custom-scrollbar-area::-webkit-scrollbar.
⁉️🤔 Frequently asked questions
Does scrollbar styling work on mobile devices?
No, in mobile browsers the scrollbar isn't displayed statically, it only appears during scrolling and is controlled by the operating system. CSS styling doesn't apply on iOS and Android. But this isn't a problem: on mobile the scrollbar isn't a permanent interface element. Verified on iOS 18 Safari and Android 15 Chrome, custom styles are ignored, the system indicator is used. On tablets with an external keyboard the scrollbar may display permanently, and styles work.
How to style horizontal scrollbar separately from vertical?
Through pseudo-elements with direction prefix:
::-webkit-scrollbar-horizontaland::-webkit-scrollbar-vertical. In practice they're rarely used, support is worse than for main pseudo-elements. More reliable to attach styles to a specific container with the needed scroll type through a class selector. For horizontal scrolling inside a code block:.code-block::-webkit-scrollbar { height: 4px; }sets the horizontal scrollbar height, and.code-block::-webkit-scrollbar-thumb { background: #666; }styles the thumb. Standardscrollbar-widthandscrollbar-colorwork the same for both directions.
Can you animate the scrollbar on hover?
Yes, through
transitionon::-webkit-scrollbar-thumb. But transition support on pseudo-elements is incomplete: Chrome and Edge work, Safari may glitch. So more often people use color change through:hoverwithout animation, more reliable and looks clean. Working variant:::-webkit-scrollbar-thumb { transition: background 0.2s ease; }smoothly changes thumb color. Don't apply transition towidth: changing scrollbar width on hover shifts content and irritates.
How to style scrollbar inside a specific block, not the entire page?
Use a compound selector:
.sidebar::-webkit-scrollbar { width: 5px; },.sidebar::-webkit-scrollbar-thumb { background: #aaa; }. For standard properties:.sidebar { scrollbar-width: thin; scrollbar-color: #aaa transparent; }. Works for any container withoverflow-y: autooroverflow-y: scroll. Don't use*selector for scrollbar, it will affect text fields and dropdown lists.
Is it mandatory to duplicate styles for ::-webkit-scrollbar and standard properties?
Yes, if cross-browser compatibility is needed. Firefox only uses
scrollbar-widthandscrollbar-color, ignoring pseudo-elements. Chrome and Edge from version 121 support both mechanisms, but apply standard properties with priority, pseudo-elements in them work as fallback for older versions. Four lines of code (two for standard, two for WebKit) cover all browsers without conflicts.
Is it worth styling the scrollbar in 2026
Definitely yes, if you're building a public site. Two lines of standard CSS give you a neat scrollbar that doesn't break the design and doesn't require polyfills. For landing pages and branded projects, WebKit pseudo-elements add individuality without hurting performance.
The main rule is don't overdo it. The scrollbar remains a functional interface element, not a canvas for experiments. Minimum width 6px, contrast no lower than 3:1, no width animations, and the user won't even notice the scrollbar is styled. And that's exactly the sign of good work.
If the site is on WordPress, throw the code into the customizer's additional styles, it will take a minute. The result will stay with you through theme updates and will please the eye of everyone who scrolls the page to the end.



