Skip to content

Everything for WordPress, web development — and beyond

🎨 Custom scrollbar in CSS: from W3C standard to WebKit gradients

🎨 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-width and scrollbar-color: two lines, full cross-browser compatibility, no prefixes.
  • Master ::-webkit-scrollbar and 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

1body {
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

1html {
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

::-webkit-scrollbar

The entire scrollbar (width, background)

::-webkit-scrollbar-track

The track (background strip)

::-webkit-scrollbar-track-piece

Part of the track not occupied by the thumb

::-webkit-scrollbar-thumb

The thumb (draggable part)

::-webkit-scrollbar-button

Arrow buttons at the ends

::-webkit-scrollbar-corner

Corner between horizontal and vertical scrollbars

::-webkit-resizer

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 */
2html {
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-horizontal and ::-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. Standard scrollbar-width and scrollbar-color work the same for both directions.

Can you animate the scrollbar on hover?

Yes, through transition on ::-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 :hover without animation, more reliable and looks clean. Working variant: ::-webkit-scrollbar-thumb { transition: background 0.2s ease; } smoothly changes thumb color. Don't apply transition to width: 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 with overflow-y: auto or overflow-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-width and scrollbar-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.