Custom Scrollbars

Custom scrollbar styling lets you restyle a browser's scroll track and thumb to match your theme using the standard scrollbar-color and scrollbar-width properties, plus the WebKit ::-webkit-scrollbar pseudo-elements for finer control.

Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.

Part of the free HTML & CSS course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

By the end you'll style any scrollbar to match your theme — in every browser — without hurting usability.

Think of a scrollbar like the volume slider on a hi-fi. The track is the groove it slides in, and the thumb is the knob you grab. Default scrollbars are the plain plastic knob the factory fitted; a custom scrollbar is the same mechanism with a knob that matches your gear. You're repainting the knob — not changing how it works — so keep it big enough to grab and easy to see.

A scrollbar has two parts you can style: the thumb (the bit you drag) and the track (the groove behind it). There are two ways to style them, and you need both.

The standard properties. scrollbar-width takes auto , thin , or none , and scrollbar-color takes two colours — thumb first, then track . These work in Firefox and modern Chrome (121+). They're simple but you only get colour and a coarse width.

The WebKit pseudo-elements. targets the whole bar, the handle, and the groove. They work in Chrome, Safari and Edge and give you exact pixel widths, border-radius, borders, gradients and :hover states — but Firefox ignores them completely.

The takeaway: write both . The standard properties cover Firefox; the WebKit pseudo-elements add the polish for everyone else.

1. Both APIs Together (Worked Example)

Read every comment, then run it. The same box gets a styled scrollbar in both Firefox and Chrome because it declares the standard properties and the WebKit pseudo-elements together.

2. Smooth Scrolling & Scroll-Snap

scroll-behavior: smooth animates jumps (handy for anchor links). scroll-snap-type makes a scroll container snap each child into place — the classic carousel feel. Note the horizontal bar uses height , not width .

3. Containing the Scroll with overscroll-behavior

When you scroll to the end of a panel, the page behind it normally takes over — that's "scroll chaining". overscroll-behavior: contain stops it, which is exactly what you want for chat windows and modals.

🎯 Your Turn #1 — Standard Properties

Fill in the blanks so the box gets a thin scrollbar with a purple thumb on a light track. This is the Firefox / standards approach — only two lines.

🎯 Your Turn #2 — WebKit Pseudo-Elements

Now do the same job the WebKit way. Decide whether each blank is width / height , thumb / track , and which :state gives hover feedback.

🏆 Mini-Challenge — Dark-Mode Chat Scrollbar

Support is faded now — you get only a comment outline. Build a subtle dark-mode scrollbar on .chat using both APIs, plus overscroll-behavior: contain . Check your work against the expected result in the comment.

💡 Pro tip: always pair the standard properties with the WebKit pseudo-elements so every browser gets a styled bar.

Practice quiz

In the standard scrollbar-color property, which order are the two colors given?

  • track then thumb
  • background then border
  • thumb then track
  • Both must be identical

Answer: thumb then track. scrollbar-color takes the thumb color first, then the track color.

Which values are valid for scrollbar-width?

  • auto | thin | none
  • small | medium | large
  • 1px | 2px | 3px
  • show | hide

Answer: auto | thin | none. scrollbar-width accepts the keywords auto, thin, or none.

Why won't ::-webkit-scrollbar rules style the scrollbar in Firefox?

  • Firefox needs a plugin
  • Firefox disables all scrollbars
  • You must use !important
  • The pseudo-elements are WebKit-only; Firefox uses the standard properties

Answer: The pseudo-elements are WebKit-only; Firefox uses the standard properties. Firefox ignores the WebKit pseudo-elements and styles scrollbars via scrollbar-width/scrollbar-color.

Which pseudo-element styles the draggable handle of a WebKit scrollbar?

  • ::-webkit-scrollbar-track
  • ::-webkit-scrollbar-thumb
  • ::-webkit-scrollbar
  • ::-webkit-scrollbar-handle

Answer: ::-webkit-scrollbar-thumb. ::-webkit-scrollbar-thumb styles the handle you drag; -track is the groove behind it.

For a horizontal scrollbar, which property sets its thickness on ::-webkit-scrollbar?

  • height
  • width
  • thickness
  • size

Answer: height. A horizontal bar's thickness is its height; vertical bars use width.

What does scroll-behavior: smooth do?

  • Changes the scrollbar color
  • Hides the scrollbar
  • Animates programmatic and anchor-link scrolling instead of jumping
  • Snaps elements into place

Answer: Animates programmatic and anchor-link scrolling instead of jumping. scroll-behavior: smooth animates jumps (anchor links, scrollIntoView); it doesn't change appearance.

What does overscroll-behavior: contain prevent?

  • The scrollbar from appearing
  • Scroll chaining to the page behind a panel
  • Smooth scrolling
  • Horizontal scrolling

Answer: Scroll chaining to the page behind a panel. overscroll-behavior: contain stops scroll chaining so the page behind a panel doesn't take over.

Which property makes a scroll container snap each child into place?

  • scroll-behavior
  • overscroll-behavior
  • scrollbar-width
  • scroll-snap-type

Answer: scroll-snap-type. scroll-snap-type (e.g. x mandatory) makes children snap into place; scroll-snap-align positions each child.

What is required for any scrollbar to appear in the first place?

  • A color-scheme declaration
  • Content that overflows a fixed-size box (height + overflow)
  • A WebKit browser
  • The scrollbar-width property

Answer: Content that overflows a fixed-size box (height + overflow). A scrollbar only shows when content overflows a box with a fixed size and overflow: auto/scroll.

Why is hiding the scrollbar on ordinary vertical content an accessibility problem?

  • It slows the page down
  • It breaks in Chrome
  • Users lose the visual cue that there is more content to read
  • It disables keyboard scrolling

Answer: Users lose the visual cue that there is more content to read. Hiding the bar (scrollbar-width: none) removes the cue that more content exists below.