-
A scrollbar appears when the content of a box exceeds the visible area of that box.
-
In HTML/CSS, every element can potentially become a scroll container if:
-
its content overflows its box
-
and its overflow behavior allows scrolling
-
-
The browser then creates a scrolling mechanism composed of:
-
scroll container (element)
-
scrollport (visible area)
-
scrollable content
-
scrollbars (UI controls)
-
scroll position (x/y offsets)
-
Requirements
-
Scrollbars only appear if the element has a constrained size.
-
Without a height/width limit, no overflow occurs.
-
Scrolling requires at least one of:
-
height / max-height
-
width / max-width
-
flex/grid constraints
-
viewport constraints (vh, vw)
-
parent layout limits
-
-
If the element can expand freely, it will not scroll.
overflow
-
This is the main rule that determines whether scrollbars exist.
-
visible(default):-
content spills out, no scrollbar.
-
-
hidden:-
content clipped, no scrollbar.
-
-
scroll:-
scrollbar always visible.
-
-
auto:-
scrollbar appears only when needed.
-
-
clip:-
like hidden, but cannot scroll programmatically.
-
Layout Impact
-
Scrollbars may:
-
take layout space (classic scrollbars)
-
overlay content (macOS, mobile)
-
auto-hide (overlay scrollbars)
-
-
This depends on OS and browser.
-
scrollbar-gutter: stable;-
reserve space for scrollbar even when not visible
-
-
scrollbar-gutter: stable both-edges;-
prevents layout shifting when scrollbars appear/disappear
-
-
Example problem:
-
container width = 100%
-
scrollbar appears → content shrinks → layout shifts
-
Solutions:
-
scrollbar-gutter: stable; -
padding-right: 12px;
-
-
Scroll Propagation
-
Scrolling bubbles up when the container reaches its limit.
-
Example:
-
inner div scrolls until end
-
then page starts scrolling
-
-
overscroll-behavior: contain;-
auto (default)
-
contain
-
none
-
Scroll Snapping
-
Optional behavior to align scroll positions:
-
scroll-snap-type: y mandatory; -
scroll-snap-align: start;
-
Customization
Standard properties (Only option for Firefox)
-
scrollbar-width: auto | thin | none-
scrollbar-width: thin;
-
-
scrollbar-color: thumb track-
scrollbar-color: #888 #222;
-
-
Supports all browsers.
-
You can use this rule to limit a style to only Firefox:
@supports (-moz-appearance: none) { /* CSS */ }
WebKit-based pseudo-elements (Chrome, Edge, Safari)
-
::-webkit-scrollbar (whole scrollbar) -
::-webkit-scrollbar-track -
::-webkit-scrollbar-track-piece-
track excluding thumb
-
-
::-webkit-scrollbar-thumb -
::-webkit-scrollbar-button-
Buttons (arrows)
-
-
::-webkit-scrollbar-corner-
(where x/y scrollbars meet)
-
-
::-webkit-resizer-
Resizer (rare). Resize handle in scrollable elements (e.g.,
<textarea>)
-
-
Pseudo-classes support :
-
Interaction states
-
:hover -
:active -
:window-inactive
-
-
Orientation
-
:horizontal -
:vertical
-
-
Increment/decrement states (buttons)
-
:increment -
:decrement
-
-
Enabled/disabled`
-
:enabled -
:disabled
-
-
Visibility
-
:corner-present(rare, mostly internal)
-
-
-
Important rules :
-
Works only in WebKit/Blink engines.
-
Firefox ignores these selectors.
-
-
The
::-webkit-scrollbarpseudo-elements do not appear in the HTML or DOM tree., because they are non-DOM pseudo-elements implemented at the rendering engine level.-
::before/::after→ part of CSS pseudo-element tree (inspectable) -
::-webkit-scrollbar→ engine-specific UI primitive (not inspectable)
-