Flexbox overflow is the bug where a flex item refuses to shrink: a long URL, an unbroken word, a code block or a wide table pushes past its container and creates a horizontal scrollbar on the whole page, even though you set flex: 1 and overflow: hidden somewhere. The symptom often shows up alongside text-overflow: ellipsis not truncating. The cause is one default value in the flexbox spec, and the fix is usually one line.
Quick fix
Flex items have min-width: auto by default, which means they will not shrink below the width of their content. Set the minimum to zero on the flex item that should shrink:
.layout {
display: flex;
}
.layout__main {
flex: 1;
min-width: 0; /* allow the item to shrink below its content width */
}
- Find the flex item that is too wide (the one containing the long content, not the content itself).
- Add
min-width: 0to it. In a column flex container, usemin-height: 0instead. - If the long content is nested several flex levels deep, add it to each flex item in the chain.
- Decide what the content should do in the space it now has: wrap, truncate or scroll.
Why flex items do not shrink: min-width: auto
For most elements, min-width: auto computes to zero. For flex items, the spec defines it as an “automatic minimum size”, which in practice is the item’s min-content width: the width of its longest unbreakable piece of content. A flex item will shrink until it hits that floor and then stop, overflowing its container.
That is a sensible default for buttons and short labels, which would otherwise squash. It becomes a problem when a flex item contains something with a large min-content width:
- long URLs, email addresses, hashes or German compound words with no break opportunities,
<pre>code blocks and anything withwhite-space: nowrap,- wide tables, images without
max-width, and embedded iframes, - nested flex or grid containers whose own children have large minimums.
The automatic minimum only applies when the item’s overflow is visible. That is why overflow: hidden on the flex item also “fixes” it, and why setting overflow on the wrong element does nothing. I prefer min-width: 0 because it states the intent and does not clip focus rings or dropdowns.
Causes, from most to least common
1. Long words, URLs and unbroken strings
A single long URL in a comment, a product SKU or a user-supplied string sets the min-content width. After min-width: 0, also allow the text to break:
.comment__body {
min-width: 0;
overflow-wrap: anywhere;
}
Use overflow-wrap: anywhere rather than break-word here. Both break long words when they would overflow, but only anywhere also reduces the element’s min-content width, so in flex and grid layouts it can fix the overflow on its own. word-break: break-all breaks between any characters even in normal words, which hurts readability.
2. Code blocks and preformatted text
Code should not wrap; it should scroll inside its own box. That requires both a shrinkable parent and an overflow on the block itself:
.article {
flex: 1;
min-width: 0;
}
.article pre {
max-width: 100%;
overflow-x: auto;
}
Without min-width: 0 on the flex item, the pre never gets a constrained width, so its overflow-x: auto has nothing to scroll against and the page scrolls instead.
3. Text truncation with ellipsis not working
text-overflow: ellipsis needs three things on the element, plus a shrinkable flex item around it:
.file-row {
display: flex;
gap: 0.5rem;
align-items: center;
}
.file-row__name {
flex: 1;
min-width: 0; /* lets the item shrink */
overflow: hidden; /* required for ellipsis */
white-space: nowrap; /* keep it on one line */
text-overflow: ellipsis;
}
.file-row__size {
flex-shrink: 0; /* never squash the metadata */
}
4. Nested flex containers (the one experienced devs miss)
You added min-width: 0 to the item with the long content and nothing changed. The reason is that its parent is also a flex item with min-width: auto, and that parent’s minimum is calculated from the child’s content. The floor propagates up the tree. Add min-width: 0 to every flex item between the overflowing content and the container that has a fixed or viewport-constrained width.
<div class="app"> <!-- display: flex -->
<aside class="sidebar">…</aside>
<main class="content"> <!-- flex item: needs min-width: 0 -->
<div class="toolbar"> <!-- display: flex -->
<span class="path">…</span> <!-- flex item: needs min-width: 0 -->
</div>
</main>
</div>
5. Column layouts that will not scroll: min-height: 0
In a flex-direction: column container, the same rule applies vertically. A classic full-height app shell with a scrolling message pane grows past the viewport instead of scrolling, because the pane’s automatic minimum height is its content height.
.shell {
display: flex;
flex-direction: column;
height: 100dvh;
}
.shell__messages {
flex: 1;
min-height: 0; /* allow it to be shorter than its content */
overflow-y: auto;
}
6. flex-basis and flex-shrink settings
flex: 1 expands to 1 1 0%, so the basis is zero and items share space. flex: auto (1 1 auto) starts from content size, so a long item takes more room. And flex-shrink: 0 or flex: none on an item means it will never shrink at all. If an item still overflows after min-width: 0, check that someone has not set flex-shrink: 0 or a fixed flex-basis in pixels on it.
The CSS Grid equivalent: minmax(0, 1fr)
Grid has the same behaviour in a different form. A 1fr track is shorthand for minmax(auto, 1fr), and that auto minimum is the content’s min-content size. One long URL in a grid cell can make the column wider than its share and break the layout.
/* Overflows when a cell contains long content */
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
/* Columns stay equal and content wraps or scrolls inside */
.grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
}
Alternatively, put min-width: 0 on the grid items themselves. I prefer minmax(0, 1fr) on the track because it fixes every cell in one place.
Step-by-step diagnosis
- Find the widest element. Paste the snippet below in the console to list elements wider than the viewport.
- Inspect its flex ancestors. In DevTools, the Elements panel marks flex and grid containers with a badge; Chrome and Firefox both offer flexbox overlays that show each item’s size and how it was resolved.
- Check computed
min-widthon each flex item up the chain. Computedautoon an item whose content overflows is the culprit. - Toggle
min-width: 0on each in turn in DevTools until the overflow disappears, then copy that into your stylesheet.
// Lists elements extending past the right edge of the viewport
const vw = document.documentElement.clientWidth;
document.querySelectorAll('body *').forEach((el) => {
const r = el.getBoundingClientRect();
if (r.right > vw + 1) console.log(Math.round(r.right - vw), 'px', el);
});
Avoid “fixing” this with overflow-x: hidden on body. It hides the symptom, can break position: sticky, and leaves content cut off on small screens.
Prevention
- Add
min-width: 0to flex items that hold variable or user-generated content as a habit. - Use
minmax(0, 1fr)for grid tracks that hold text. - Set a global
img, video, iframe { max-width: 100%; height: auto; }baseline. - Wrap tables and code blocks in containers with
overflow-x: auto. - Test layouts with long, unbroken strings and on narrow mobile widths. Content that overflows only after it loads can also contribute to layout shift.
Key takeaways
- Flexbox overflow happens because flex items default to
min-width: auto, which is their content width. min-width: 0on the flex item (ormin-height: 0in columns) lets it shrink.- Nested flex containers need the fix on every flex item in the chain.
- Use
overflow-wrap: anywherefor long strings andoverflow-x: autofor code and tables. - In grid, replace
1frwithminmax(0, 1fr).
Frequently asked questions
Why does my flex item overflow its container?
Flex items have an automatic minimum width equal to their content’s min-content width, so they will not shrink below their longest word, URL or code line. Setting min-width: 0 removes that floor.
Why is text-overflow ellipsis not working in flexbox?
The flex item cannot shrink because of min-width: auto. Add min-width: 0 along with overflow: hidden, white-space: nowrap and text-overflow: ellipsis.
What is the difference between overflow-wrap break-word and anywhere?
Both break long words that would overflow, but anywhere also lowers the element’s min-content width, so it can resolve flex and grid overflow while break-word cannot.
Why does my grid column grow wider than 1fr?
A 1fr track has a minimum of auto, the content’s min-content size. Use minmax(0, 1fr) so the column can shrink below its content.
If your layouts break on real content or on mobile and you want them fixed properly, get in touch.