Why Flex Items Refuse to Shrink

Published 3 Jun 2026

A practical guide to why flex items overflow instead of shrinking, how automatic minimum sizes work, and when min-width: 0 or min-height: 0 is the missing CSS rule.

Flexbox is supposed to make layout easier.

You put some things in a row. You give the parent display: flex. You expect the children to share the available space.

Then one item refuses to cooperate.

The title pushes the card wider than the screen. A long URL breaks the layout. An ellipsis does not appear even though you wrote text-overflow: ellipsis. A sidebar looks fine until the content gets just a little too long.

It feels like Flexbox is ignoring you.

It is not. The browser is protecting the content.

That protection is useful, but it is also the reason flex items sometimes refuse to shrink. If Flexbox still feels unpredictable overall, start with the broader CSS Survival Guide: The 20% That Solves 80% of Layout Problems.


The common broken layout

A typical example looks like this:

<div class="row">
  <img class="avatar" src="avatar.jpg" alt="" />
  <div class="content">
    <h2 class="title">A very long title that should truncate instead of breaking the layout</h2>
    <p>Some supporting text.</p>
  </div>
</div>
.row {
  display: flex;
  gap: 1rem;
}

.avatar {
  width: 48px;
  height: 48px;
  flex: none;
}

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

You expect the title to shrink and show an ellipsis.

But sometimes the whole row becomes wider than its container instead.

The confusing part is that the title has the usual ellipsis rules. It has white-space: nowrap, overflow: hidden, and text-overflow: ellipsis.

The missing rule is often not on the title itself.

It is on the flex item that contains it.

.content {
  min-width: 0;
}

That one line can fix the entire layout.


Flex items have an automatic minimum size

The key detail is this: flex items do not always shrink as much as you think they can.

By default, a flex item has an automatic minimum size. In simple terms, the browser tries not to make the item smaller than its content.

That sounds reasonable. The browser is trying to avoid crushing text, images, forms, tables, and other content into unreadable shapes.

But in UI layout, that helpful default can become a problem.

If a flex child contains a long unbroken title, URL, filename, table, code block, or image, the flex child may decide that it needs to be at least as wide as that content.

So even though the parent is flexible, the child says:

I can shrink, but not smaller than my content.

That is why the layout overflows. For a deeper look at sideways scrolling, clipping, and scroll containers, read The Hidden Complexity of CSS Overflow.


min-width: 0 gives the item permission to shrink

When you write this:

.content {
  min-width: 0;
}

You are telling the flex item:

You are allowed to become smaller than your content's preferred width.

That allows the inner text to actually clip, wrap, or truncate inside the available space.

A more complete pattern looks like this:

.row {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.avatar {
  width: 48px;
  height: 48px;
  flex: none;
}

.content {
  min-width: 0;
}

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

The important part is that min-width: 0 goes on the flex child that needs to shrink, not always on the text element itself.

In this example, .content is the flex item. .title is just a child inside it.

If the shrinking works but the row still looks visually misaligned, that is a different problem. Start with Why align-items: center Feels Broken.


flex: 1 does not always solve it

A common first attempt is this:

.content {
  flex: 1;
}

That is often useful, but it does not always fix shrinking.

flex: 1 tells the item how to grow and shrink relative to other flex items. But the automatic minimum size can still limit how small the item is allowed to get.

So this may still overflow:

.content {
  flex: 1;
}

While this behaves the way you expected:

.content {
  flex: 1;
  min-width: 0;
}

Think of them as solving different problems:

flex: 1      = take available space
min-width: 0 = you are allowed to get smaller than your content

They often belong together.


The same problem appears in card layouts

This is not only a media-object problem.

Imagine a card inside a flexible layout:

.cards {
  display: flex;
  gap: 1rem;
}

.card {
  flex: 1;
}

If one card contains a long heading, long link, or wide child, it can push the entire row wider than expected.

The fix may be:

.card {
  flex: 1;
  min-width: 0;
}

Then the content inside the card can wrap, clip, or scroll according to its own rules instead of forcing the card wider.

This is especially common with:

  • long product names
  • URLs
  • email addresses
  • filenames
  • code snippets
  • tables
  • badges or pills in a row
  • nested grids

When a flex layout works with normal content but breaks with real content, check the minimum size.


Long words and URLs need their own rules

min-width: 0 lets the flex item shrink, but it does not magically decide how text should break.

For normal text, wrapping usually works fine:

.content {
  min-width: 0;
}

For long unbroken strings, you may also need:

.content {
  min-width: 0;
  overflow-wrap: anywhere;
}

Or, for code-like content:

pre {
  overflow-x: auto;
}

Different content wants different behavior.

A paragraph should probably wrap.

A title might truncate.

A code block might scroll horizontally.

A table might need a dedicated scroll wrapper.

The layout rule and the content rule are related, but they are not the same thing.


Ellipsis has several requirements

Text truncation is one of the most common places this bug appears.

For single-line ellipsis, the text element usually needs:

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

But the parent flex item may also need:

.content {
  min-width: 0;
}

Without that parent rule, the title may never become narrow enough for the ellipsis to matter.

The browser cannot show clipped text if the box refuses to become smaller than the text.

So when ellipsis does not work, check both levels:

  1. Does the text element have the truncation rules?
  2. Is the flex item allowed to shrink?

The second question is the one people often miss.


Sometimes the problem is vertical

There is a vertical version of this problem too.

In column flex layouts, children can refuse to shrink vertically. This often appears in app shells, sidebars, modals, and panels.

For example:

.app {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.header {
  flex: none;
}

.main {
  flex: 1;
  overflow: auto;
}

If .main does not scroll the way you expect, the missing rule may be:

.main {
  flex: 1;
  min-height: 0;
  overflow: auto;
}

min-width: 0 helps items shrink horizontally.

min-height: 0 helps items shrink vertically.

This matters whenever a flex column contains a scrollable child. Without it, the child may expand to fit its content instead of becoming a constrained scroll area.

Nested scroll areas have their own tradeoffs. If the scrolling behavior itself feels surprising, read The Hidden Complexity of CSS Overflow.


Grid has a similar gotcha

This problem is not exclusive to Flexbox.

Grid items also have automatic minimum sizes, and they can also overflow when content refuses to shrink.

You may see fixes like this:

.main {
  min-width: 0;
}

Or grid tracks written like this:

.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
}

That minmax(0, 1fr) says the flexible column is allowed to shrink all the way down to zero if the layout requires it.

A plain 1fr column can sometimes behave as though its minimum is based on the content. That is helpful until the content is wider than the available space.

If a grid column overflows for no obvious reason, the same mental model applies: something has a minimum size you did not account for.

This detail also shows up in sticky sidebar layouts. If the sidebar itself is the confusing part, read Why position: sticky Feels Broken.


Do not put min-width: 0 everywhere without thinking

It is tempting to treat min-width: 0 as magic dust.

It is useful, but it is not a design strategy by itself.

Before adding it everywhere, ask what you want the content to do when space runs out.

Should it wrap?

Should it truncate?

Should it scroll?

Should the layout stack instead?

For example, a row of buttons might be better with wrapping:

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

A code block might be better with horizontal scrolling:

pre {
  overflow-x: auto;
}

A page section might be better with a responsive grid or a media query.

min-width: 0 gives the layout permission to shrink. You still need to decide what happens to the content after that.


A debugging checklist

When a flex item refuses to shrink, check these in order:

  1. Which element is the flex container?
  2. Which direct child is the flex item?
  3. Is the overflowing content inside that flex item?
  4. Does the flex item need min-width: 0?
  5. If the layout is vertical, does it need min-height: 0?
  6. Is flex: 1 being used for growth but not minimum size?
  7. Is the content a long unbroken string?
  8. Should the content wrap, truncate, or scroll?
  9. Is a child image, table, or code block forcing the width?
  10. Would the layout be clearer as grid or with wrapping?

The most useful habit is to inspect the boxes.

Find the flex container. Find the direct child that is too wide. Then check whether that child has an automatic minimum size getting in the way.


The rule of thumb

If a flex row overflows and a child refuses to get narrower, try this on the flex item:

.child {
  min-width: 0;
}

If a flex column has a scrollable area that refuses to fit, try this:

.child {
  min-height: 0;
}

Then decide how the content itself should behave:

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

Or:

.content {
  overflow-wrap: anywhere;
}

Or:

pre {
  overflow-x: auto;
}

Flexbox is not ignoring your layout. It is following a minimum-size rule that is easy to forget.

Once you know that rule, the bug stops feeling random.

The item was not refusing to shrink out of spite. It was waiting for permission.