EmpireUI
Get Pro
← Blog7 min read#scrollbar#css#webkit

Scrollbar Styling in CSS: Webkit, Firefox and the New Standard

Custom scrollbars in CSS are finally getting real cross-browser support. Here's how webkit, Firefox, and the new scrollbar-width spec all fit together in 2026.

Developer styling a browser scrollbar with CSS custom properties on a dark monitor

Why Scrollbar Styling Has Always Been a Mess

For years, customizing scrollbars meant writing a pile of ::-webkit-scrollbar rules and just hoping Firefox users would tolerate the OS default. There was no standard. Webkit did its own thing in 2009, Firefox eventually added scrollbar-color and scrollbar-width in Firefox 64 (2018), and the two APIs have almost nothing in common. You'd write duplicate code or pick a side.

That said, the landscape in 2026 is dramatically better. The CSS Scrollbars specification is now a W3C standard, Chrome and Edge have added partial support for the standard properties, and Safari is finally catching up. You can write something close to a single set of rules that works almost everywhere — with a webkit fallback for the detailed stuff.

Honestly, the gap still annoys me. The standard properties give you color and width control, but zero geometry control. If you want a 6px scrollbar with rounded ends and a custom track color, you're still writing webkit-specific CSS. That's just the reality right now.

The Webkit API: `::-webkit-scrollbar` and Friends

Webkit's pseudo-element approach is verbose but genuinely powerful. You get full control over every pixel. The main pseudo-elements are ::-webkit-scrollbar, ::-webkit-scrollbar-thumb, ::-webkit-scrollbar-track, ::-webkit-scrollbar-button, and ::-webkit-scrollbar-corner. Most of the time you only need three of them.

Here's a minimal dark-mode scrollbar that's 8px wide with rounded thumb corners — something you'd actually use in production: ``css /* Webkit — Chrome, Edge, Safari */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: #1a1a2e; border-radius: 4px; } ::-webkit-scrollbar-thumb { background: #7c3aed; border-radius: 4px; border: 2px solid #1a1a2e; background-clip: padding-box; } ::-webkit-scrollbar-thumb:hover { background: #9d5cff; } ``

That border trick on the thumb — 2px solid matching your track color — creates a fake margin around the thumb without any hacks. It's one of those CSS tricks that's been circling the internet since 2015 and still works perfectly. Worth noting: background-clip: padding-box is required for the border transparency to work correctly, otherwise you get a weird artifact.

Quick aside: avoid styling ::-webkit-scrollbar-button unless you have a very specific reason. Those little arrows at the top and bottom of the scrollbar are almost universally hidden in modern design, and styling them inconsistently across OS themes causes more problems than it solves.

The Standard API: `scrollbar-width` and `scrollbar-color`

The W3C CSS Scrollbars spec gives you two properties: scrollbar-width and scrollbar-color. Simple, intentionally limited. scrollbar-width accepts auto, thin, or none. scrollbar-color takes two color values — thumb first, then track. ``css /* Standard — Firefox, Chrome 121+, Edge 121+ */ .sidebar { scrollbar-width: thin; scrollbar-color: #7c3aed #1a1a2e; } ``

That's it. No pseudo-elements, no geometry control, no hover states. What you gain is a clean API that respects the OS scrollbar context better. On some systems, thin maps to about 6px. On others it's wider. You're trusting the browser to interpret your intent, which is either liberating or frustrating depending on how much of a control freak you are.

Firefox has supported this since version 64, so you've had cross-Firefox coverage for ages. Chrome and Edge added support starting in version 121 (early 2024). Safari's support landed in Safari 17.4. So in 2026, you can reasonably use these properties as your primary approach and layer the webkit rules as an enhancement.

Writing a Cross-Browser Scrollbar That Actually Works

The cleanest approach is to write the standard properties first, then add the webkit block. Browsers that support both will use both — the webkit block wins for Chromium-based browsers because it's more specific. Firefox ignores webkit pseudo-elements entirely. It's a natural cascade. ``css /* ✅ Cross-browser scrollbar — paste this into your globals */ .custom-scroll { /* Standard API */ scrollbar-width: thin; scrollbar-color: #7c3aed #0f0f1a; /* Webkit override for geometry control */ &::-webkit-scrollbar { width: 8px; } &::-webkit-scrollbar-track { background: #0f0f1a; } &::-webkit-scrollbar-thumb { background-color: #7c3aed; border-radius: 4px; border: 2px solid #0f0f1a; background-clip: padding-box; } } ``

Using CSS nesting here (supported in all major browsers since 2024) keeps the webkit rules scoped inside the same block. No more hunting through a stylesheet for the matching webkit rules. One more thing — if you're using Tailwind 4, you can wrap this in a @utility block and compose it as a class.

If you want to hide the scrollbar entirely but keep scroll functionality — a common pattern for horizontal carousels — use scrollbar-width: none with -webkit-scrollbar: { display: none } as the fallback. Don't use overflow: hidden for this; it blocks scroll events completely, which is almost never what you want.

Scrollbars and Design Systems: Context Matters

Default OS scrollbars look jarring inside a polished design. If you're building something themed — say, a cyberpunk dashboard or an aurora-inspired UI — an unstyled scrollbar sticks out like a sore thumb. The 16px Windows scrollbar circa 2010 is not a vibe anyone is going for in 2026.

Look, you don't need to style every scrollbar in your app. Scoping your custom scroll styles to specific containers — a sidebar, a code editor panel, a modal body — is almost always the right call. Global ::-webkit-scrollbar rules tend to cause weird interactions with third-party components that expect OS defaults.

If you're exploring more opinionated UI aesthetics, the glassmorphism components on Empire UI already ship with scroll containers that use scoped custom scrollbar rules. Same for the navigation styles. It's a good reference for how to scope these properly without blowing up your entire component tree. You can also use the box shadow generator to visually test track styling alongside your component shadows.

Common Mistakes and Edge Cases

The biggest mistake? Setting overflow: scroll on a container with scrollbar-width: none and then wondering why the scrollbar still shows up — because you've got an outer ancestor with scrolling that's overriding your styles. Always check which element is actually scrolling with DevTools.

Percentage widths on ::-webkit-scrollbar don't work. It's 2026 and they still don't. Use fixed px values. Also avoid very small scrollbars (under 4px) without testing on Windows — the hit target becomes essentially unusable for mouse users, and Windows scales things differently than macOS.

Worth noting: scrollbar-gutter is a related property that's worth adding to your toolkit. It reserves space for the scrollbar even when it's not visible, preventing layout shift when content overflows. Combined with scrollbar-width: thin, it makes overflow transitions much less jarring: ``css .panel { scrollbar-gutter: stable both-edges; scrollbar-width: thin; } ``

If you're building something where scrollbar appearance is part of a larger interactive experience — custom cursors, animated UI transitions — take a look at how cursors and scrollbars are handled together on Empire UI. They share the same philosophy: scoped, intentional, and non-invasive to the rest of the DOM.

What's Still Missing From the Standard

The CSS Scrollbars spec is useful but incomplete. There's still no standard way to control thumb border-radius, add hover effects, or set a specific pixel width beyond the vague thin keyword. The CSSWG has discussed extending the spec, but nothing concrete has shipped as of mid-2026.

In practice, if you need pixel-perfect scrollbar design — a real product requirement, not an aesthetic whim — you still need the webkit approach. It's not deprecated, it's not going away, and Chromium browsers support it fully. Just treat it as progressive enhancement layered on top of the standard properties.

The good news is that browsers are finally converging on something. Three years ago you had to pick: write webkit-only and ignore Firefox, or write standard-only and lose all geometry control. Now you can do both in 15 lines of CSS. That's real progress, even if it's slower than anyone wanted.

FAQ

Can I style scrollbars in Firefox with `::-webkit-scrollbar`?

No — Firefox ignores all webkit pseudo-elements entirely. Use scrollbar-color and scrollbar-width for Firefox. Write both sets of rules and they'll apply to the right browser automatically.

How do I hide a scrollbar but keep scroll functionality?

Set scrollbar-width: none for Firefox and &::-webkit-scrollbar { display: none } for Webkit. Never use overflow: hidden — it kills scroll events, not just the visual track.

Does `scrollbar-color` support hover states?

No. The standard API has no hover state support at all. If you need thumb color changes on hover, you need the webkit pseudo-element approach with ::-webkit-scrollbar-thumb:hover.

What's the minimum scrollbar width I should use for accessibility?

Keep it at least 6px, ideally 8px. Below 4px the hit target becomes basically unusable for mouse users, and Windows DPI scaling can make narrow scrollbars disappear entirely.

Free components in 40 styles
React & Tailwind, copy-paste ready.
Browse →

Read next

CSS Box Shadow: The Complete Guide With Live ExamplesCSS border-radius Patterns: From Rounded to Blob ShapesWhat Is Glassmorphism? A Free React + Tailwind GuideTailwind Gradient Text: bg-clip-text in Under 2 Minutes