Command Palette

Search for a command to run...

Hectal
PHASE 5Beginner ~21 min· topic 6 of 8

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, scroll or auto.
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.

Pick what happensdiagram
Rendering diagram…

03Scroll one axis only

A wide table on a phone: let it scroll sideways inside its wrapper, without making the whole page scroll.

style.csswhole filecss
.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.

style.csswhole filecss
.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.

style.csswhole filecss
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

Try it yourself

  1. 1

    Change the overflow value

    In the first example, change .auto to overflow: 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. 2

    Make clip keep a shadow

    In the second example, add box-shadow: 0 0 0 6px tomato to .tall and overflow-clip-margin: 6px to .clip. The clipped box now lets 6px of the shadow show outside its padding edge.

  3. 3

    Turn smooth off

    In the third example, remove scroll-behavior: smooth and click the button again. The jump is now instant.

Code & diagrams

The overflow values New tab

`scrollHeight` is the full content height; `clientHeight` is what the box shows. Scroll the third box with your mouse wheel.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

content height: 200 visible height: 80
auto box scrolled to: 50
hidden vs clip, and the visible-becomes-auto rule New tab

`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

Press Run to see the page.

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: auto
scrollbar-gutter and smooth scrolling New tab

On 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

Press Run to see the page.

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; }.

terminal
$ the page shows
── what you'll see ──
The sideways scroll is gone, but a `position: sticky` header stops sticking and part of the content is cut off on the right

Break #2

Cut-off focus rings and shadows

Put buttons with a focus outline inside a card with overflow: hidden.

terminal
$ the page shows
── what you'll see ──
When a keyboard user tabs to a button at the card's edge, half of its focus ring is missing

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: clip became available in all major browsers in 2022; overflow-clip-margin landed later and with partial support (it may only accept certain box values in some engines). Check support before relying on it.

  • ▸

    scrollbar-gutter is 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-edges reserves 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 scroll event listeners force work on the main thread; use IntersectionObserver or CSS scroll-driven animations instead.

  • ▸

    overscroll-behavior: contain stops scroll chaining (a modal's list scrolling the page behind it when it reaches the end), and scroll-snap-type makes carousels snap. scrollbar-width and scrollbar-color style scrollbars in a standard way.

Remember this

  1. 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 overflow property decides what the browser does about it, and it can be set per axis with overflow-x and overflow-y (or the logical overflow-inline and overflow-block).

  2. 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. hidden cuts 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. clip cuts it off too, but forbids all scrolling, even by script. scroll always shows scrollbars, even when nothing overflows. auto shows scrollbars only when needed, which is what you want almost every time.

  3. 3

    Any value except visible and clip turns 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 that position: sticky sticks inside (Topic 6.2), which is why sticky headers break inside an overflow: hidden ancestor.

  4. 4

    The two axes are linked. If one axis is visible and the other is hidden, scroll or auto, the visible one **computes to auto** (and clip computes to hidden). So overflow-x: hidden alone often adds a vertical scrollbar you didn't ask for. overflow: clip (with overflow-clip-margin to let shadows peek out) is the tool when you want to cut one axis without creating a scroll container.

  5. 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: stable reserves 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. 6

    scroll-behavior: smooth on a scroll container (or on html for the whole page) makes jumps to #anchor links and script calls like scrollTo() 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

01

Explain the five overflow values and when you'd use each.

02

What is a scroll container, and what side effects does creating one have?

03

Why does overflow-x: hidden alone often add a vertical scrollbar?

04

What problem does scrollbar-gutter: stable solve?

Practice

01

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).

02

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.

  • ↔

    hidden is supported everywhere and creates a BFC (sometimes useful); clip has no side effects but is newer.

Done when you can

  • I can pick the right overflow value for a situation.

  • I know hidden is still scrollable by script and clip isn'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.