Topic 5.6
Overflow and Scrolling
In one line
When content is bigger than its box, overflow decides what happens: spill out (visible), cut off (hidden, clip), or scroll (scroll, auto); scrollbar-gutter and scroll-behavior polish how scrolling looks and feels.
Think of it like this
Pouring too much juice into a glass. With an open glass it spills over the edge onto the table (visible). Put a lid on and the extra juice simply isn't there to see (hidden). Use a glass with a straw you can move up and down to reach any part of the juice (scroll/auto). The glass is the box; the juice is the content.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Overflow
- Content that is bigger than the box meant to hold it.
- overflow: visible
- The default: extra content spills out of the box and is drawn over its neighbours.
- overflow: hidden
- Cut off the extra content and show no scrollbar. Scripts can still scroll it.
- overflow: clip
- Cut off the extra content and forbid any scrolling, even from scripts.
- overflow: auto
- Show a scrollbar only when the content doesn't fit.
- Scroll container
- A box whose content can scroll inside it. Made by
overflow: hidden,scrollorauto. - scrollbar-gutter
- A property that reserves room for the scrollbar so the layout doesn't jump when it appears.
- scroll-behavior
- A property that makes jumps to anchors and script scrolling smooth instead of instant.
Step by step
01Make content overflow
Give a box a fixed height of 80px and put 200px of content in it. By default (visible) the content spills out of the bottom and overlaps whatever comes next, but the next box doesn't move.
02Pick what happens
Decide whether the content must stay reachable. If yes, scroll it. If it's decoration that may be cut, hide or clip it.
03Scroll one axis only
A wide table on a phone: let it scroll sideways inside its wrapper, without making the whole page scroll.
.table-wrap {
overflow-x: auto; /* overflow-y computes to auto as well */
}04Stop the layout jump
A chat panel gets a scrollbar once messages fill it, and all messages shift left by the scrollbar's width. Reserve the space from the start.
.chat {
height: 300px;
overflow-y: auto;
scrollbar-gutter: stable;
}05Smooth, but respectful, scrolling
Turn on smooth scrolling only for people who haven't asked their system to reduce motion.
@media (prefers-reduced-motion: no-preference) {
html {
scroll-behavior: smooth;
}
}Try it yourself
- 1
Change the overflow value
In the first example, change
.autotooverflow: scroll. Predict: does the box look different even though it's the same content? (It now shows a horizontal scrollbar too, with nothing to scroll, on classic-scrollbar systems.) - 2
Make clip keep a shadow
In the second example, add
box-shadow: 0 0 0 6px tomatoto.tallandoverflow-clip-margin: 6pxto.clip. The clipped box now lets 6px of the shadow show outside its padding edge. - 3
Turn smooth off
In the third example, remove
scroll-behavior: smoothand click the button again. The jump is now instant.
Code & diagrams
`scrollHeight` is the full content height; `clientHeight` is what the box shows. Scroll the third box with your mouse wheel.
Preview
Console
Nothing logged yet.Expected console output
content height: 200 visible height: 80
auto box scrolled to: 50`hidden` is still a scroll container (the stripes moved up 30px); `clip` is not. And a lone `overflow-x: hidden` silently turns the other axis into `auto`.
Preview
Console
Nothing logged yet.Expected console output
hidden, after scrollTop = 30: 30
clip, after scrollTop = 30: 0
overflow-y when only overflow-x is hidden: autoOn Windows or Linux with classic scrollbars, the second panel keeps an empty strip where a scrollbar would go. With overlay scrollbars (macOS, phones) both look the same.
Preview
Console
Nothing logged yet.Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
overflow: hidden on body to stop sideways scrolling
Something is 20px too wide, so you add body { overflow-x: hidden; }.
Break #2
Cut-off focus rings and shadows
Put buttons with a focus outline inside a card with overflow: hidden.
Myth vs fact
Myth
overflow: hidden makes content impossible to scroll.
Fact
The user gets no scrollbar, but JavaScript (scrollTop, scrollIntoView) and focus moving into hidden content can still scroll it. Only overflow: clip forbids all scrolling.
Myth
overflow: scroll and overflow: auto are the same.
Fact
scroll always shows scrollbars (on classic-scrollbar systems), even with nothing to scroll. auto shows them only when needed.
Myth
Overflowing content pushes other elements away.
Fact
With visible, overflowing content paints over its neighbours but takes no space in the layout. Only the box's own size counts for layout.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
overflow: clipbecame available in all major browsers in 2022;overflow-clip-marginlanded later and with partial support (it may only accept certain box values in some engines). Check support before relying on it. - ▸
scrollbar-gutteris supported in Chrome, Edge and Firefox, and in Safari from 18.2 (late 2024). It only has a visible effect with classic scrollbars;scrollbar-gutter: stable both-edgesreserves space on both sides to keep content centred. - ▸
Every scroll container is a candidate for the browser's compositor thread: scrolling it can happen without running layout or JavaScript, which keeps it smooth. Heavy
scrollevent listeners force work on the main thread; useIntersectionObserveror CSS scroll-driven animations instead. - ▸
overscroll-behavior: containstops scroll chaining (a modal's list scrolling the page behind it when it reaches the end), andscroll-snap-typemakes carousels snap.scrollbar-widthandscrollbar-colorstyle scrollbars in a standard way.
Remember this
- 1
Overflow happens when content needs more room than its box gives it: long text in a fixed-height box, a wide table in a narrow column, an image wider than its container. The
overflowproperty decides what the browser does about it, and it can be set per axis withoverflow-xandoverflow-y(or the logicaloverflow-inlineandoverflow-block). - 2
The five values:
visible(the default) lets content spill out of the box and paint over whatever is next to it; it doesn't push other boxes away.hiddencuts the content at the padding edge and shows no scrollbar, but the box can still be scrolled by JavaScript or by focusing something inside it.clipcuts it off too, but forbids all scrolling, even by script.scrollalways shows scrollbars, even when nothing overflows.autoshows scrollbars only when needed, which is what you want almost every time. - 3
Any value except
visibleandclipturns the box into a scroll container: a box whose content can be scrolled inside it. A scroll container also starts a new block formatting context (Topic 5.3), so it contains floats and stops margins collapsing through it. It also becomes the box thatposition: stickysticks inside (Topic 6.2), which is why sticky headers break inside anoverflow: hiddenancestor. - 4
The two axes are linked. If one axis is
visibleand the other ishidden,scrollorauto, thevisibleone **computes toauto** (andclipcomputes tohidden). Sooverflow-x: hiddenalone often adds a vertical scrollbar you didn't ask for.overflow: clip(withoverflow-clip-marginto let shadows peek out) is the tool when you want to cut one axis without creating a scroll container. - 5
Classic scrollbars take space from the box (often about 15px on Windows), so when content grows enough to need one, the content area gets narrower and everything jumps sideways.
scrollbar-gutter: stablereserves that space in advance, so the layout doesn't shift. On systems with overlay scrollbars (macOS, phones), scrollbars float over the content and take no space, so the problem doesn't appear there. - 6
scroll-behavior: smoothon a scroll container (or onhtmlfor the whole page) makes jumps to#anchorlinks and script calls likescrollTo()animate instead of jumping. Respect people who get motion sickness: wrap it in@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }. Other text overflow tools live in the typography phase (text-overflow: ellipsis,overflow-wrap: anywhere).
Explain it without notes
Explain the five overflow values and when you'd use each.
What is a scroll container, and what side effects does creating one have?
Why does overflow-x: hidden alone often add a vertical scrollbar?
What problem does scrollbar-gutter: stable solve?
Practice
Make a .code box 200px tall that scrolls vertically only when its content is taller. Fill it with 400px of content and log scrollHeight and clientHeight (no padding or border on the box).
Show that a overflow: clip box can't be scrolled by script, but an overflow: hidden one can. Log both scrollTop values after setting them to 40.
Trade-offs
- ↔
Inner scroll areas keep long content contained, but nested scrolling is harder to use on touch screens and for keyboard users; prefer letting the page scroll unless a panel really needs its own scroll.
- ↔
hiddenis supported everywhere and creates a BFC (sometimes useful);cliphas no side effects but is newer.
Done when you can
I can pick the right
overflowvalue for a situation.I know
hiddenis still scrollable by script andclipisn't.I can explain the visible-becomes-auto rule.
I can stop layout shift with
scrollbar-gutter: stable.I can add smooth scrolling that respects reduced motion.
I can find the element causing sideways page scrolling instead of hiding it.