CSS Reference Guide

All TopicsPlayground

CSS Scrollbar Styling

Customize scrollbar appearance, control scroll behavior with snap points and smooth scrolling, and manage overscroll effects — all with CSS.

ScrollingUI CustomizationScroll SnapUX

scrollbar-width

The standard CSS property to control scrollbar thickness. Supported in Firefox and modern Chromium browsers.

scrollbar-width values
.container {
  scrollbar-width: auto;    /* default platform scrollbar */
  scrollbar-width: thin;    /* thinner scrollbar */
  scrollbar-width: none;    /* hide scrollbar (still scrollable) */
}
Accessibility note: scrollbar-width: none hides the scrollbar but the content remains scrollable via keyboard, touch, and mouse wheel. However, it removes a visual cue, so use sparingly and provide alternative navigation hints.

scrollbar-color

Sets the thumb and track colors with a single property. Takes two color values: thumb first, then track.

scrollbar-color syntax
.container {
  /* scrollbar-color: thumb-color track-color */
  scrollbar-color: #6366f1 #1e1e2e;
  scrollbar-width: thin;
}

/* Auto = use system default colors */
.default {
  scrollbar-color: auto;
}

/* Using CSS variables for theming */
.themed {
  scrollbar-color: var(--scroll-thumb) var(--scroll-track);
}

WebKit Scrollbar Pseudo-Elements

Chrome, Safari, Edge, and other WebKit/Blink browsers support detailed scrollbar styling with pseudo-elements. These offer much more control than the standard properties.

WebKit Scrollbar Pseudo-Elements
/* The entire scrollbar */
.container::-webkit-scrollbar {
  width: 10px;           /* vertical scrollbar width */
  height: 10px;          /* horizontal scrollbar height */
}

/* The scrollbar track (background) */
.container::-webkit-scrollbar-track {
  background: #1e1e2e;
  border-radius: 10px;
}

/* The draggable thumb */
.container::-webkit-scrollbar-thumb {
  background: #6366f1;
  border-radius: 10px;
  border: 2px solid #1e1e2e;  /* creates visual gap */
}

/* Thumb on hover */
.container::-webkit-scrollbar-thumb:hover {
  background: #818cf8;
}

/* Corner where both scrollbars meet */
.container::-webkit-scrollbar-corner {
  background: #1e1e2e;
}
Cross-Browser Scrollbar Styling
/* Standard (Firefox, modern Chrome 121+) */
.scrollable {
  scrollbar-width: thin;
  scrollbar-color: #6366f1 transparent;
}

/* WebKit fallback (older Chrome, Safari, Edge) */
.scrollable::-webkit-scrollbar {
  width: 8px;
}
.scrollable::-webkit-scrollbar-track {
  background: transparent;
}
.scrollable::-webkit-scrollbar-thumb {
  background-color: #6366f1;
  border-radius: 4px;
}

Live Scrollbar Demos

Scroll inside each box to see different scrollbar styles in action.

Thin Minimal Scrollbar

This container has a thin, minimal scrollbar. The track is transparent and the thumb is a subtle indigo.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra.

Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing.

Colored Scrollbar (Pink/Purple)

This container has a vibrant pink/purple scrollbar with a tinted track background.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus lacinia odio vitae vestibulum vestibulum.

Cras venenatis euismod malesuada. Nullam ac erat ante. Vivamus vel risus ac nisl sodales fermentum.

Suspendisse potenti. Fusce lacinia arcu et nulla. Nulla vitae massa quis enim semper malesuada.

Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat.

Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.

Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus.

Dark Theme Scrollbar

This container uses a dark theme scrollbar with subtle gray tones that blend into the dark background.

Perfect for dark mode interfaces where the scrollbar shouldn't draw too much attention.

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium.

Totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt.

Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit.

Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.

Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam.

Hidden Scrollbar (Still Scrollable)

No visible scrollbar! But you can still scroll with mouse wheel, trackpad, or keyboard.

This is useful for custom scroll UIs, carousels, or sleek sidebar designs.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor.

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore.

Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia.

scrollbar-gutter

The scrollbar-gutter property reserves space for the scrollbar even when content doesn't overflow, preventing layout shifts when content grows.

scrollbar-gutter values
.container {
  overflow: auto;

  /* auto = default, space only when scrollbar appears */
  scrollbar-gutter: auto;

  /* stable = always reserve space for scrollbar */
  scrollbar-gutter: stable;

  /* stable both-edges = reserve space on both sides (symmetrical) */
  scrollbar-gutter: stable both-edges;
}
Prevent layout jump: Use scrollbar-gutter: stable on containers where content might dynamically grow to require scrolling. This prevents the annoying horizontal shift when the scrollbar appears.

scroll-behavior: smooth

Enables smooth animated scrolling for programmatic scrolls and anchor link navigation.

scroll-behavior
/* Apply to the scrolling container (usually html) */
html {
  scroll-behavior: smooth;
}

/* Or on specific containers */
.scroll-container {
  overflow-y: auto;
  scroll-behavior: smooth;
}

/* Respect user preference for reduced motion */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

Scroll Snap

CSS Scroll Snap provides precise control over scroll positions, making carousels and paginated scrolling trivially easy without JavaScript.

Scroll Snap Properties
/* On the scroll container */
.carousel {
  overflow-x: auto;
  scroll-snap-type: x mandatory;  /* x|y|both  mandatory|proximity */
  scroll-padding: 0 1rem;        /* offset snap position */
}

/* On each child item */
.carousel-item {
  scroll-snap-align: start;      /* start | center | end */
  scroll-snap-stop: always;      /* normal | always (prevents skipping) */
}

/* scroll-snap-type keywords:
   mandatory — always snaps to a snap point after scrolling
   proximity — snaps only when near a snap point */
Horizontal Scroll Snap Carousel
Full-Page Vertical Scroll Snap
.fullpage {
  height: 100vh;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
}

.fullpage-section {
  height: 100vh;
  scroll-snap-align: start;
  display: flex;
  align-items: center;
  justify-content: center;
}

overscroll-behavior

Controls what happens when scrolling reaches the boundary of a scroll container. Prevents scroll chaining (the parent scrolling when a child reaches its limit) and the pull-to-refresh gesture.

overscroll-behavior values
.modal-body {
  overflow-y: auto;

  /* auto = default, scroll chains to parent */
  overscroll-behavior: auto;

  /* contain = prevent scroll chaining, no bounce */
  overscroll-behavior: contain;

  /* none = prevent chaining AND rubber-band/bounce effects */
  overscroll-behavior: none;
}

/* Axis-specific */
.sidebar {
  overscroll-behavior-y: contain;  /* only prevent vertical chaining */
  overscroll-behavior-x: auto;     /* allow horizontal chaining */
}

/* Common use: prevent page behind modal from scrolling */
.modal-content {
  overflow-y: auto;
  overscroll-behavior: contain;
}
Use case: When a user scrolls to the bottom of a modal or sidebar and keeps scrolling, overscroll-behavior: contain prevents the background page from scrolling. This is essential for good modal UX.

Gotchas

WebKit pseudo-elements and standard properties can conflict. If both are applied, behavior varies by browser. Use the standard properties (scrollbar-width, scrollbar-color) as the primary approach and WebKit pseudo-elements as a fallback for older browsers.
scrollbar-width: none hides but doesn't disable scrolling. The content is still scrollable via keyboard, touch, and mouse wheel. This can confuse users who rely on visible scrollbars to discover scrollable content.
scroll-snap-type: mandatory can trap users. If snap points are far apart, the user may not be able to scroll freely to see content between snap points. Use proximity for a less aggressive snap.
scroll-behavior: smooth doesn't affect JS scroll methods by default. element.scrollTo() uses instant scrolling unless you pass { behavior: 'smooth' }. The CSS property affects anchor links and scrollIntoView().
Safari has limited scrollbar customization. Safari supports ::-webkit-scrollbar pseudo-elements but with some restrictions. Test thoroughly on Safari.

Pro Tips

Always pair scroll-behavior: smooth with prefers-reduced-motion. Some users experience motion sickness with smooth scrolling. Always provide an instant fallback.
Use scroll-padding with scroll-snap and sticky headers. If you have a fixed/sticky header, use scroll-padding-top to offset the snap position so content doesn't hide behind the header.
scroll-padding with sticky header
html {
  scroll-behavior: smooth;
  scroll-padding-top: 80px;  /* height of fixed header */
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
Fade-in scrollbar on hover. Show scrollbars only when the user hovers over the container for a cleaner UI.
Show scrollbar on hover only
.container {
  overflow-y: auto;
  scrollbar-width: none;
}

.container:hover {
  scrollbar-width: thin;
  scrollbar-color: rgba(99,102,241,0.4) transparent;
}
Use overscroll-behavior on chat windows and side panels. Any scrollable UI that sits on top of a scrollable page should use overscroll-behavior: contain to prevent the background from scrolling.

Browser Support

Feature Chrome Firefox Safari Edge
scrollbar-width121+64+--121+
scrollbar-color121+64+--121+
::-webkit-scrollbarAll--YesAll
scroll-snap-type69+68+11+79+
scroll-behavior61+36+15.4+79+
overscroll-behavior63+59+16+18+
scrollbar-gutter94+97+--94+
PreviousShapes & Clip-Path