---
title: 'Overflow Management'
source: 'https://academia.sh/en/courses/css-fundamentals/overflow-management'
course: 'Visual Presentation with CSS'
language: en
updated: '2026-08-17T18:09:15+00:00'
license: 'CC BY-SA 4.0'
---

# Overflow Management

Handling the case where content does not fit its box; comparing overflow values, the separate mechanisms for text overflow, and clipping's accessibility cost.

Throughout this topic, boxes were sized, arranged, and overlapped. One situation has not been
addressed: what happens when content does not **fit** its box?

The situation is unavoidable. A long station name does not fit a narrow cell, a nine-column
measurement table does not fit a narrow screen, a long caption does not fit a card given a
fixed height. This lesson takes up what overflow is, what each of the options costs, and why
text overflow is a separate matter.

## Overflow's Default Behavior Is Visibility

When a box's content does not fit the box, the default behavior is for the content to
**spill out and stay visible**. It is not clipped, not hidden, and does not grow the box.

This choice is deliberate: content that disappears is worse than content that breaks the
layout. Overflowing text stays visible and readable; the problem is seen and can be fixed.

```js
// overflow.mjs — computes whether content fits the box and the result of each overflow value
function overflowState({ boxWidth, boxHeight, contentWidth, contentHeight, overflow }) {
  const horizontal = Math.max(0, contentWidth - boxWidth);
  const vertical = Math.max(0, contentHeight - boxHeight);
  const result = {
    "visible": { visible: true,  scrollable: false, clips: false },
    "hidden":  { visible: false, scrollable: false, clips: true  },
    "clip":    { visible: false, scrollable: false, clips: true  },
    "scroll":  { visible: false, scrollable: true,  clips: true  },
    "auto":    { visible: false, scrollable: horizontal > 0 || vertical > 0, clips: true },
  }[overflow];
  return { horizontal, vertical, ...result };
}

const box = { boxWidth: 320, boxHeight: 120 };
const content = { contentWidth: 480, contentHeight: 200 };
console.log(`box ${box.boxWidth}x${box.boxHeight}, content ${content.contentWidth}x${content.contentHeight}`);
for (const value of ["visible", "hidden", "clip", "scroll", "auto"]) {
  const r = overflowState({ ...box, ...content, overflow: value });
  console.log(`${value.padEnd(8)} overflow=${r.horizontal}x${r.vertical}  visible from outside=${String(r.visible).padEnd(5)} scrollable=${String(r.scrollable).padEnd(5)} clips=${r.clips}`);
}

console.log("\n--- content that fits ---");
for (const value of ["scroll", "auto"]) {
  const r = overflowState({ ...box, contentWidth: 300, contentHeight: 100, overflow: value });
  console.log(`${value.padEnd(8)} overflow=${r.horizontal}x${r.vertical}  scrollable=${r.scrollable}`);
}

console.log("\n--- a long word fitting a line ---");
const word = "North-Slope-Automatic-Measurement-Station";
const CHAR_WIDTH = 8;   // an example font's character width
const boxWidth = 160;
const fits = Math.floor(boxWidth / CHAR_WIDTH);
console.log(`word ${word.length} characters x ${CHAR_WIDTH}px = ${word.length * CHAR_WIDTH}px`);
console.log(`box ${boxWidth}px -> ${fits} characters fit a line, overflow ${word.length * CHAR_WIDTH - boxWidth}px`);
const pieces = word.match(new RegExp(`.{1,${fits}}`, "g"));
console.log("split with overflow-wrap: anywhere:");
for (const p of pieces) console.log(`  |${p.padEnd(fits)}|`);
```

```
box 320x120, content 480x200
visible  overflow=160x80  visible from outside=true  scrollable=false clips=false
hidden   overflow=160x80  visible from outside=false scrollable=false clips=true
clip     overflow=160x80  visible from outside=false scrollable=false clips=true
scroll   overflow=160x80  visible from outside=false scrollable=true  clips=true
auto     overflow=160x80  visible from outside=false scrollable=true  clips=true

--- content that fits ---
scroll   overflow=0x0  scrollable=true
auto     overflow=0x0  scrollable=false

--- a long word fitting a line ---
word 41 characters x 8px = 328px
box 160px -> 20 characters fit a line, overflow 168px
split with overflow-wrap: anywhere:
  |North-Slope-Automati|
  |c-Measurement-Statio|
  |n                   |
```

## Comparing the Five Values

`visible` — the initial value. Content overflows and stays visible. The box itself does not
grow; its neighbors have no knowledge of the overflow and can be painted over it.

`hidden` — the overflowing part is clipped and becomes **unreachable**. No scrollbar is
shown, but the box is still a box that can be scrolled programmatically; a focused element can
be brought into the visible area.

`clip` — clips like `hidden` but does not make the box scrollable. The clipping is final.

`scroll` — the overflowing part is clipped and a scrollbar is **always** shown.

`auto` — clips and shows a scrollbar **only when needed**.

The output's second block gives the difference between these last two values: when content
fits the box, `scroll` still produces a scrollable box, `auto` does not. In some environments a
scrollbar takes up space; writing `scroll` in this case reserves a strip and narrows the box
even when content fits. If scrolling should appear only when needed, `auto` is written.

## The Cost of Clipping

Writing `overflow: hidden` is a frequently reached-for fix, and it is used for two different
purposes. The two need to be told apart.

The first use is **deliberate clipping**: fitting an image into a box, keeping a decorative
shape from spilling out. What is clipped here carries no information.

The second use is **making the overflow problem invisible**: content does not fit, and hiding
it pretends the problem has gone away. This does not solve the problem; it hides it from the
user. Clipped text can still be read by a screen reader but is visually unreachable; a user
navigating by keyboard can focus it but cannot see it.

The distinction is made with this question: **is it acceptable for the clipped thing to be
lost?** If the answer is no, `hidden` is not written — `auto` is written instead, or the box's
size is made flexible.

There is one more side effect, and it has come up twice in earlier lessons: an `overflow`
value other than `visible` makes the box an **independent formatting root**. Floated children
are included in the height, margin collapsing stops at the box's boundary. This is why writing
`overflow: hidden` sometimes produces a layout change that looks unrelated.

## Two Axes Separately

`overflow` is a shorthand; it sets the `overflow-x` and `overflow-y` longhands. Their logical
counterparts are `overflow-inline` and `overflow-block`.

The two axes can be given different values, but there is a constraint: if one axis is
`visible` while the other takes a clipping value, the `visible` axis is treated like `auto`.
The two axes are not independent; a box that clips in one direction cannot leave overflowing
content visible in the other.

Horizontal scrolling needs special handling. The way to show a wide measurement table on a
narrow screen is to place the table inside a horizontally scrollable box. Such a box must also
be reachable by keyboard; giving a scrollable region `tabindex="0"` and naming it with an
accessible name is the counterpart of this.

## Text Overflow Is a Separate Mechanism

The output's third block points to a different problem. A forty-one-character word does not
fit a 160-unit box and overflows by 168 units. This is not a problem to be solved with
`overflow` — the word needs to be **broken**.

Line-breaking rules are managed by separate properties:

`overflow-wrap: anywhere` — breaks a word that does not fit at any point. The output's last
lines showed the break made under this rule. The `break-word` value does similar work but is
not included in the box's minimum content size calculation.

`word-break: break-all` — breaks words whether or not they fit; it pays no attention to word
integrity.

`hyphens: auto` — hyphenates according to the document's language and puts a hyphen at the
break point. It requires the `lang` attribute to be declared; this is one more counterpart of
the `lang="en"` declaration written on the root element in the Web Fundamentals and HTML
course.

`white-space: nowrap` — does the opposite: prevents line breaking altogether. This does not
prevent overflow, it guarantees it.

`text-overflow: ellipsis` — puts an ellipsis at the end of overflowing text. It does not work
alone; the box must be clipping and must be a single line:

```css
.station-name {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
```

The three declarations are written together. It must not be forgotten that the clipped text is
lost: the full name should stay reachable in a `title` attribute or somewhere else.

```css
/* station.css — step 15: overflow */
.table-wrapper {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

.measurement-table { min-width: 40rem; }

.card .description {
  overflow-wrap: anywhere;
  hyphens: auto;
}

.location-image img { overflow: clip; }
```

`.table-wrapper` makes the table horizontally scrollable on a narrow screen; the `min-width`
declaration keeps the table from being squeezed into unreadability. Together, the two choose
to scroll the table rather than shrink it.

`overscroll-behavior-x: contain` keeps the page from shifting once the box's own scrolling
ends — it keeps the scroll chain stopping at that box.

## Summary

- Overflow's default behavior is visibility: content spills outside the box and stays
  readable. This rests on the assumption that lost content is worse than a broken layout.
- `hidden` and `clip` clip; `scroll` always shows a scrollbar, `auto` shows one only when
  needed; when content fits, `scroll` still produces a scrollable box.
- An `overflow` value other than `visible` makes the box an independent formatting root; it
  contains floated children and stops margin collapsing at its boundary.
- The two axes are not independent: while one axis clips, the other cannot stay `visible`, and
  is treated like `auto`.
- A word that does not fit is solved not with `overflow` but with line-breaking properties;
  `text-overflow: ellipsis` does not work alone, it is written together with clipping and
  single-line declarations.

## Next Step

This topic built the size, arrangement, and boundaries of boxes. The page that results is
structured but colorless: every decision so far concerned geometry. The next topic takes up
visual properties, and the first question is color itself — how a color is written, in which
space it is defined, and how the contrast between two colors turns into a number.
