CSS Overflow

Every element in CSS has a content box, but the content inside that box doesn’t always fit. Text can be longer than its container, an image can be wider than its wrapper, or a list can grow taller than a fixed-height panel. The overflow property tells the browser what to do when that happens: let it spill out, cut it off, or add scrollbars so the user can reach it. Understanding overflow is essential for building layouts that don’t visually break when content is unpredictable, which is almost always the case on real websites.

Overview / How it works

When the browser lays out a box, it first determines the size of the content box based on the element’s width, height, padding, and border (the box model). If the actual rendered content — text, images, child elements — is larger than that content box, the content technically “overflows” the box’s edges. What the browser does next is controlled entirely by the overflow property.

There are four core keyword values:

  • visible (the default): overflow is not clipped. Content renders outside the box, potentially overlapping neighboring elements. No scrollbar is created.
  • hidden: overflow is clipped at the padding edge, and the clipped portion becomes inaccessible — there is no scrollbar and no way to scroll to it with the keyboard or mouse.
  • scroll: overflow is clipped, but the browser always shows scrollbars (horizontal and/or vertical, depending on the axis) so the user can pan to see the rest, even if the content currently fits.
  • auto: the browser clips and adds scrollbars only when needed. If the content fits, no scrollbar appears; if it doesn’t, one does. This is the value used in practice most of the time.

A fifth value, clip, behaves like hidden but additionally forbids programmatic scrolling (you can’t scroll it via JavaScript either), and it does not establish a scroll container at all — it’s a hard, permanent clip.

Crucially, setting overflow to anything other than visible does more than just clip content. It also establishes a new Block Formatting Context (BFC) for the element. A BFC is an isolated layout environment: floated children inside it are “contained” (the parent will expand to wrap them instead of collapsing to zero height), and margins of children won’t collapse through the parent’s margin. This is why overflow: hidden or overflow: auto is a classic (if slightly old-fashioned) technique for “clearing floats” — it’s really a side effect of BFC creation, not something overflow was designed to do.

Overflow can also be controlled per axis using overflow-x and overflow-y. The overflow property itself is shorthand: overflow: hidden auto; sets overflow-x: hidden and overflow-y: auto. If you only supply one keyword, both axes get that value.

Syntax

selector {
  overflow: visible | hidden | clip | scroll | auto;
  overflow-x: visible | hidden | clip | scroll | auto;
  overflow-y: visible | hidden | clip | scroll | auto;
}
Part Meaning
overflow Shorthand controlling both axes at once (one value = both axes; two values = x then y)
overflow-x Controls horizontal overflow only
overflow-y Controls vertical overflow only
visible Default; content spills outside the box, unclipped
hidden Clips content at the padding edge; not reachable by scrolling
scroll Always shows a scrollbar, even when content fits
auto Shows a scrollbar only when content actually overflows
clip Like hidden, but disallows scrolling entirely (no scroll container created)

Examples

Example 1: A scrollable fixed-height box

Applied to a <div class=”box”> containing a long paragraph of text:

.box {
  width: 300px;
  height: 150px;
  padding: 16px;
  border: 1px solid #ccc;
  overflow: auto;
}

Result: The box stays exactly 300px by 150px (plus padding and border). Because the text is longer than 150px tall, a vertical scrollbar appears on the right edge of the box, letting the user scroll to read the rest. If the text had been short enough to fit, no scrollbar would appear at all — that’s the defining behavior of auto versus scroll.

Example 2: Independent horizontal and vertical control

A common pattern for a code preview panel or sidebar that should never scroll sideways but can scroll vertically:

.panel {
  width: 100%;
  max-height: 400px;
  overflow-x: hidden;
  overflow-y: auto;
  background-color: #1e1e1e;
  color: #eee;
  padding: 12px;
}

Result: Any content wider than the panel (like a long unbroken line of code) is clipped horizontally with no way to reveal it, while content taller than 400px produces a vertical scrollbar. This keeps the layout’s width stable regardless of content while still letting users reach long lists or logs vertically.

Example 3: Truncating text with an ellipsis

Applied to a <h3 class=”title”> whose text might be longer than its column width:

.title {
  width: 220px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

Result: The heading is forced onto a single line by white-space: nowrap. Anything wider than 220px is clipped by overflow: hidden, and instead of an abrupt cut, text-overflow: ellipsis replaces the last visible characters with “…” so the truncation looks intentional. This three-property combination is the standard recipe for single-line text truncation and only works because all three are present — text-overflow alone does nothing without overflow set to something other than visible, and without white-space: nowrap the text would simply wrap instead of truncating.

How it works step by step

  1. The browser computes the element’s content box size from its width/height and box-model properties (padding, border, per the current box-sizing).
  2. It lays out the element’s content (text runs, inline boxes, child elements) using normal flow, floats, or flex/grid rules — whichever applies.
  3. It compares the content’s rendered extent to the content box. If the content is larger in either dimension, an “overflow” condition exists on that axis.
  4. The computed overflow-x/overflow-y values are consulted independently. Per the CSS Overflow specification, if one axis is visible and the other is not, the browser silently computes the visible one as auto instead — you cannot have overflow escape on only one axis while the other clips, because that would make the clipping axis’s scroll mechanism ambiguous.
  5. If any computed value is not visible, the element becomes a scroll container: the browser establishes a BFC, creates an internal scrollable area sized to the content’s full extent, and clips the visible viewport of that area to the padding box.
  6. Scrollbars are then drawn according to the value: never for hidden/clip, always for scroll, and conditionally for auto based on whether overflow is actually present.

Common Mistakes

Mistake 1: Using overflow: hidden to clear floats, then losing tooltips and shadows

Developers often reach for overflow: hidden purely to contain floated children, forgetting it also clips anything else that visually extends past the box — including box-shadow, dropdown menus, and absolutely positioned tooltips.

.card {
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}

This is valid CSS, but the shadow will be invisible because it falls outside the padding box that overflow: hidden clips. The fix is to separate concerns: apply a modern clearfix (or a layout method that doesn’t need clearing, like Flexbox or Grid) instead of overflow, and reserve overflow for elements that genuinely need clipping or scrolling.

.card::after {
  content: "";
  display: table;
  clear: both;
}

.card {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}

Mistake 2: Expecting text-overflow to work without overflow and white-space

.label {
  width: 150px;
  text-overflow: ellipsis;
}

This is syntactically valid but does nothing visible: without overflow set to hidden (or clip) there is nothing to truncate, and without white-space: nowrap the text just wraps onto a new line instead of overflowing horizontally. All three properties are required together:

.label {
  width: 150px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

Mistake 3: Assuming overflow-x and overflow-y act fully independently

Setting overflow-x: visible; overflow-y: hidden; on the same element does not give you “clip vertically, spill horizontally” as many expect. Per the spec rule described above, the browser converts the visible axis to auto automatically, so horizontal content will get a scrollbar (or be clipped-and-scrollable) rather than freely overflowing. If you need one axis to truly spill unclipped, don’t set the other axis to hidden/scroll/auto at all — restructure the layout instead (for example, move the overflowing element outside the clipping ancestor).

Best Practices

  • Default to overflow: auto over overflow: scroll unless you specifically want scrollbars to always be visible (e.g., to avoid layout shift when content changes size).
  • Never rely on overflow: hidden as your only float-clearing mechanism in modern layouts — prefer Flexbox or Grid, which don’t require clearing at all.
  • When you need clipping that should never be scrollable even via script or keyboard, use overflow: clip instead of hidden.
  • Always pair text-overflow: ellipsis with an explicit overflow value (not visible) and white-space: nowrap.
  • Before adding overflow: hidden to a container, check whether any descendant depends on visually escaping it (tooltips, dropdowns, focus rings, negative-margin decorations).
  • Use overflow-x/overflow-y individually when you only want to constrain one axis, but remember the visible-axis auto-conversion rule.
  • Test scrollable regions with keyboard navigation (Tab and arrow keys) to make sure they’re actually reachable, not just visually present.

Practice Exercises

  • Create a <div> with a fixed width and height smaller than its text content, and use overflow so only a vertical scrollbar appears when needed (not a horizontal one).
  • Build a navigation bar item whose label truncates with an ellipsis when the sidebar is narrowed to 160px, using the three-property text-truncation pattern.
  • Take a card component with overflow: hidden that is accidentally clipping its own box-shadow, and rewrite the CSS so the shadow is visible while floated children are still contained.

Summary

  • overflow controls what happens when content is larger than its box: visible (default, spills out), hidden (clipped, unreachable), scroll (always shows scrollbars), auto (scrollbars only when needed), and clip (hard clip, no scrolling at all).
  • Any non-visible overflow value creates a scroll container and establishes a new Block Formatting Context, which is why overflow: hidden/auto also contains floats.
  • overflow-x and overflow-y set each axis independently, but a visible axis paired with a non-visible axis is automatically computed as auto.
  • text-overflow: ellipsis only works when combined with overflow: hidden (or clip) and white-space: nowrap.
  • Clipping overflow can hide unrelated visual elements like shadows, tooltips, and dropdowns — apply it deliberately, not as a blanket float-fix.