Guide to Custom Scrollbar Styling with Tailwind CSS v4
I had to style the scrollbar with custom styling in Tailwind CSS. I did it the following way:
Guide to Custom Scrollbar Styling with Tailwind CSS v4
Photo by FONG on Unsplash
I had to style the scrollbar with custom styling in Tailwind CSS. I did it the following way:
The Quick and Dirty: Inline Scrollbar Styling
When I first discovered Tailwind’s arbitrary value selectors, I was probably too excited. Here’s the approach I started with — throwing scrollbar styles directly into className attributes:
<div className="[&::-webkit-scrollbar]:[width:6px] [&::-webkit-scrollbar-thumb]:bg-gray-400 overflow-y-auto [&::-webkit-scrollbar-thumb]:[border-radius:3px] max-h-80">
<div className="p-4 space-y-4">
{/*scrollable content*/}
{Array.from({length: 20}).map((_, i) => (
<div key={i} className="bg-white p-4 rounded-lg shadow">
Item {i + 1}
</div>
))}
</div>
</div>
This works, and it’s fast. But let’s be honest — that className is getting pretty unwieldy. And if you’re like me, you’ll want to use this styling in multiple places. Copy-pasting that monster of a className string? Not fun.
Here’s what each piece does:
[&::-webkit-scrollbar]:[width:6px]makes the scrollbar nice and thin (6px wide)[&::-webkit-scrollbar-thumb]:bg-gray-400gives the draggable part a subtle gray color[&::-webkit-scrollbar-thumb]:[border-radius:3px]adds just a touch of rounding to keep things modern
It’s functional, but we can do better.
Building a Reusable Scrollbar System
After dealing with scrollbar styling in a few different components, I realized I needed a better approach. Here’s what I came up with — a dedicated utility that I can reuse across my entire application:
lib/scrollbar.ts
export const customScrollbar = [
// Basic sizing - thin but not too thin
"[&::-webkit-scrollbar]:w-1.5",
"[&::-webkit-scrollbar]:h-1.5",
// The draggable thumb
"[&::-webkit-scrollbar-thumb]:bg-gray-300",
"[&::-webkit-scrollbar-thumb]:rounded-md",
// Smooth interactions feel professional
"[&::-webkit-scrollbar-thumb]:transition-colors",
"[&::-webkit-scrollbar-thumb]:duration-200",
"[&::-webkit-scrollbar-thumb:hover]:bg-gray-400",
// Clean track and hidden buttons
"[&::-webkit-scrollbar-track]:bg-transparent",
"[&::-webkit-scrollbar-button]:hidden"
].join(" ");
Now using custom scrollbars becomes as simple as:
import { customScrollbar } from './lib/scrollbar';
type ProductListProps = {
products: any[];
};
function ProductList({ products }: ProductListProps) {
return (
<div className={`${customScrollbar} overflow-y-auto max-h-96 p-4`}>
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
Much cleaner, right? And if you decide you want to tweak the hover color or make the scrollbar a pixel wider, you change it in one place and it updates everywhere.
Understanding What You’re Actually Styling
Before we go further, let’s talk about what these WebKit pseudo-elements actually control. Think of a scrollbar as having four main parts:
The Container (::-webkit-scrollbar) This is the entire scrollbar area. Here you control width for vertical scrollbars, height for horizontal ones.
The Thumb (::-webkit-scrollbar-thumb) This is the part users actually drag. It's where you'll spend most of your styling effort - colors, hover states, border radius, borders, even gradients if you're feeling fancy.
The Track (::-webkit-scrollbar-track)
The background area the thumb slides along.
The Buttons (::-webkit-scrollbar-button) Those little arrow buttons at the ends.
Final Thoughts
Custom scrollbars might seem like a small detail, but they’re one of those finishing touches that separate good interfaces from great ones.
메타데이터
- post_id
- a7c8fce28e88
- slug
- guide-to-custom-scrollbar-styling-with-tailwind-css-v4-a7c8fce28e88
- url
- https://medium.com/@lyecre/guide-to-custom-scrollbar-styling-with-tailwind-css-v4-a7c8fce28e88
- canonical_url
- https://medium.com/@lyecre/guide-to-custom-scrollbar-styling-with-tailwind-css-v4-a7c8fce28e88
- author_url
- https://medium.com/@lyecre
- status
- ok
- fetched_at
- 2026-07-18 05:46:27