Skip to main content

CSS overflow property

CSS overflow defines what happens when content is too big for its container: it can spill out, get clipped, or become scrollable.

Theory

TL;DR

  • Fish tank analogy: visible lets water spill everywhere, hidden seals it shut, scroll adds permanent drain pipes, auto adds pipes only when the tank overflows.
  • Main difference: auto shows scrollbars only when content exceeds the box; scroll always renders them.
  • overflow: hidden also triggers a Block Formatting Context (BFC), which wraps floated children automatically.
  • Decision rule: hidden to crop UI cleanly (cards, avatars), auto for dynamic content like chat logs or sidebars.

Quick example

css
/* Clips child to rounded corners - standard card pattern */ .card { overflow: hidden; border-radius: 12px; width: 300px; height: 200px; } /* Scrollbar appears only when messages exceed the container */ .chat { overflow-y: auto; max-height: 400px; /* Without this, the box just grows forever */ }

The first rule crops any child that sticks outside the card boundary. The second keeps a fixed-height message list and adds a vertical scrollbar only when needed.

Values at a glance

ValueBehavior
visibleDefault. Content renders outside the box.
hiddenClips content. No scrollbar. JS scrollTop still works.
scrollScrollbars always visible, even on short content.
autoScrollbar appears only when content overflows.
clipLike hidden, but JS scrollTop has no effect.

Key difference

auto and scroll both make content scrollable, but scroll always renders scrollbar tracks regardless of content size. On some platforms that reserves space and shifts layout. auto is the safer default. Use scroll when you need the scrollbar always present visually, for example a horizontal navigation row where you want a hint that content continues off-screen.

overflow-x and overflow-y

You can control axes independently:

css
/* Horizontal scrolling row, vertical overflow hidden */ .tag-list { overflow-x: auto; overflow-y: hidden; white-space: nowrap; -webkit-overflow-scrolling: touch; /* Native feel on iOS */ }

This pattern appears in tag lists, horizontal carousels, and Bootstrap's .table-responsive component.

When to use

  • Fixed card with long text: overflow: hidden (clean crop)
  • Chat log, sidebar, modal body: overflow-y: auto with a max-height
  • Horizontal nav or data table: overflow-x: auto for small screens
  • Body element during modal open: overflow: hidden blocks background scroll
  • Rounded card or avatar: overflow: hidden clips the image to the border shape

overflow: hidden and BFC

Setting overflow to hidden, auto, or scroll creates a Block Formatting Context. The practical result: the container wraps its floated children instead of collapsing to zero height. This was the standard float-clearing technique before display: flow-root existed. You will still see it in older codebases.

css
.container { overflow: hidden; /* BFC: wraps floated children, no height collapse */ }

Common mistakes

Forgetting height with overflow: auto.

css
/* Wrong: box grows forever, scroll never triggers */ .list { overflow-y: auto; } /* Fix: constrain the height */ .list { overflow-y: auto; height: 300px; }

Without a height or max-height, the container just expands. There is nothing to overflow against.

Assuming overflow: hidden clips both axes.

css
/* Child can still spill horizontally */ .parent { overflow: hidden; } .child { width: 500px; } /* Fix: target the axis you need */ .parent { overflow-x: hidden; }

Using overflow: scroll on mobile. Always-visible scrollbars can conflict with native scroll behavior, producing double scroll tracks on some platforms. Use overflow: auto with -webkit-overflow-scrolling: touch for a native feel.

Mixing up hidden and clip. Both clip visually. clip also blocks JS scrollTop. If you need to control scroll position in code, use hidden.

Real-world usage

  • shadcn/ui Dialog: overflow: auto on .modal-body for scrollable modal content
  • TailwindCSS: overflow-hidden on card components in Next.js templates
  • Bootstrap: .table-responsive uses overflow-x: auto for wide tables on mobile
  • VS Code: sidebar panels combine overflow: hidden with resize handles

Follow-up questions

Q: What is the difference between overflow: hidden and overflow: clip?
A: Both clip content visually. clip also blocks all scroll events, including JS scrollTop. hidden allows programmatic scrolling. Use hidden if you ever need to move scroll position in code.

Q: How does overflow interact with flexbox?
A: Setting overflow on a flex container only clips or scrolls the overflow. It does not affect how flex items are aligned. Set overflow on the item itself if you want individual items to scroll.

Q: Why does overflow-x: auto show no scrollbar when content fits?
A: Browsers hide the scrollbar track until content actually overflows. That is the whole point of auto. Use scroll if you need the track always visible.

Q: How does overflow: hidden on body prevent background scroll during a modal, and what breaks on iOS Safari?
A: It clips the body's scrollable area so the user cannot scroll behind the modal. iOS Safari's momentum scroll can bypass this. The fix: body { overflow: hidden; position: fixed; width: 100%; }. Be aware this resets scrollY to 0, so save and restore the position manually if needed.

Examples

Clipping an image to a card shape

html
<style> .card { width: 250px; height: 180px; overflow: hidden; border-radius: 12px; } .card img { width: 100%; height: 100%; object-fit: cover; } </style> <div class="card"> <img src="photo.jpg" alt="Profile photo" /> </div>

Without overflow: hidden, the image corners stick out past the rounded border. With it, the image clips to the card shape. This is the same pattern TailwindCSS uses on card components in its default templates.

Scrollable chat container

jsx
function ChatMessages({ messages }) { return ( <div style={{ height: '400px', overflowY: 'auto', /* Scroll only when needed */ border: '1px solid #ccc', padding: '8px' }}> {messages.map(msg => ( <div key={msg.id}>{msg.text}</div> ))} </div> ); }

The container stays at 400px. Once messages push past that height, a scrollbar appears. Remove height: 400px and the scrollbar never shows up, no matter how many messages load. That is the mistake that shows up most often in code review.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?