Flexbox Won’t Shrink? Check the Wrapper’s Minimum Size

When flex-shrink and ellipsis leave a row overflowing, find the flex item that owns the minimum size and fix the wrapper without clipping the whole card.

Share
A long orange bar extends beyond the edge of a dark browser panel beside a fixed orange block.

The file name has an ellipsis rule. The row has flex: 1. And yet the Download button is halfway out of the card. Before you turn the shrink factor up to eleven, inspect the flex item that contains the name. A flex item can agree to shrink and still have a minimum size that says, effectively, “not that far.”

In a horizontal flex row, try min-inline-size: 0 on the direct flex item that needs to give up space (min-width: 0 in the usual horizontal writing mode). Keep the ellipsis rules on the box that contains the text. If that box sits inside another flex row, check the outer wrapper too: the inner text can't truncate while an ancestor is still insisting on room for all of it.

This is an AI-prepared, documentation-based explainer, not a personally reproduced incident. The examples are illustrative and were not run in a browser for this article. See the editorial policy.

The clue is which box is too wide

Imagine a file card with a small icon and a details row. Inside the details row there's a filename and a Download button. Short names look fine. Feed it an unbroken build artifact name and the whole page starts scrolling sideways. The obvious suspect is the text: did someone forget overflow: hidden? But if the filename box is already as wide as the text inside it, there's nothing to clip there. The wrong box is overflowing.

flex-shrink helps distribute a shortage of space. Minimum sizes can clamp the resulting sizes. The Flexbox specification's automatic minimum rule says a flex item with non-scrollable computed overflow has a content-based automatic minimum on the main axis. In a plain text wrapper with no other sizing constraints, a long unbreakable name can drive that floor. Images, aspect ratios and definite size constraints have additional rules; “the longest word” is a useful clue here, not the general formula.

There's a quick way to tell the two bugs apart in DevTools. Start with the box that's too wide and look at its parent. If the parent is a flex container, toggle min-inline-size: 0 on that direct child. Then look at what moved. If the card fits but the Download button is still pushed out of the details row, you've fixed one boundary and found the next. If all the boxes already fit but the letters spill, check the text box's wrapping and overflow instead. And if neither toggle changes anything, check for an explicit minimum, a fixed width or a sibling that can't fit on its own.

Fix the sizing boundary, then choose what the text does

Here's an illustrative two-row version. The outer flex item is .details; the inner flex item is .name. The button and icon keep their own space. The filename gets what's left.

<div class="file">
  <span class="icon" aria-hidden="true">↳</span>
  <div class="details">
    <span class="name">release_build_0123456789abcdef0123456789abcdef.zip</span>
    <button class="download">Download</button>
  </div>
</div>
.file, .details {
  display: flex;
  align-items: center;
  gap: .5rem;
}
.file { inline-size: min(100%, 18rem); }
.icon, .download { flex: none; }

.details, .name {
  flex: 1 1 auto;
  min-inline-size: 0;
}
.name {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

Try removing the minimum override from .details only. That's the useful experiment: the filename still has every ellipsis declaration, but its wrapper can refuse to shrink to the width left by the icon. In this example the explicit minimum on .name also makes the intent clear; its overflow: hidden already affects the automatic minimum. The important override is on the outer wrapper, where you don't want to clip everything just to get the math right.

That distinction explains why overflow: hidden can look like a magic sizing fix. CSS treats hidden as a scrollable overflow value even though it doesn't expose scrolling controls; the box can still be scrolled programmatically. clip is different: it doesn't create a scroll container and doesn't zero the automatic minimum the same way. See the CSS Overflow definitions. Set the minimum where you need shrinkage, and put clipping only where you actually intend to hide content.

For filenames users must read or copy, consider wrapping instead. If wrapping is acceptable, drop the no-wrap and ellipsis rules, and try overflow-wrap: anywhere. Its break opportunities count toward min-content sizing; those from break-word don't. For a column flex layout whose main axis is the block axis, look for the same problem in min-block-size and put scrolling on the intended pane. Neither minimum override creates space when the fixed controls alone exceed the card width; change the layout or let those controls wrap.

Make the card prove it can get small

Test the component at its narrowest supported width with a long unbroken name, zoomed text, and a longer translated button label. Check that the button stays visible and keyboard focus isn't clipped. If you truncate a name that matters, give users a way to see or copy it in full. In a browser test, assert that the action remains inside the card; an ellipsis screenshot by itself won't tell you which box overflowed.

The next time a layout looks like it ignored a CSS rule, inspect the boundary where that rule takes effect. That's also the useful habit in Debugly's DOM layout thrashing investigation, where the trick is to separate reads and writes before blaming the render loop.