Why don't flex items shrink past content size?
The Automatic Minimum Size of Flex Items
You're encountering a flexbox default setting.
A flex item cannot be smaller than the size of its content along the main axis.
The defaults are...
min-width: auto
min-height: auto
...for flex items in row-direction and column-direction, respectively.
You can override these defaults by setting flex items to:
min-width: 0
min-height: 0
overflow: hidden
(or any other value, exceptvisible
)
Flexbox Specification
4.5. Automatic Minimum Size of Flex Items
To provide a more reasonable default minimum size for flex items, this specification introduces a new
auto
value as the initial value of themin-width
andmin-height
properties defined in CSS 2.1.
With regard to the auto
value...
On a flex item whose
overflow
isvisible
in the main axis, when specified on the flex item’s main-axis min-size property, specifies an automatic minimum size. It otherwise computes to0
.
In other words:
- The
min-width: auto
andmin-height: auto
defaults apply only whenoverflow
isvisible
. - If the
overflow
value is notvisible
, the value of the min-size property is0
. - Hence,
overflow: hidden
can be a substitute formin-width: 0
andmin-height: 0
.
and...
- The minimum sizing algorithm applies only on the main axis.
- For example, a flex item in a row-direction container does not get
min-height: auto
by default. - For a more detailed explanation see this post:
- min-width rendering differently in flex-direction: row and flex-direction: column
You've applied min-width: 0 and the item still doesn't shrink?
Nested Flex Containers
If you're dealing with flex items on multiple levels of the HTML structure, it may be necessary to override the default min-width: auto
/ min-height: auto
on items at higher levels.
Basically, a higher level flex item with min-width: auto
can prevent shrinking on items nested below with min-width: 0
.
Examples:
- Flex item is not shrinking smaller than its content
- Fitting child into parent
- white-space css property is creating issues with flex
Browser Rendering Notes
Chrome vs. Firefox / Edge
Since at least 2017, it appears that Chrome is either (1) reverting back to the
min-width: 0
/min-height: 0
defaults, or (2) automatically applying the0
defaults in certain situations based on a mystery algorithm. (This could be what they call an intervention.) As a result, many people are seeing their layout (especially desired scrollbars) work as expected in Chrome, but not in Firefox / Edge. This issue is covered in more detail here: flex-shrink discrepancy between Firefox and ChromeIE11
As noted in the spec, the
auto
value for themin-width
andmin-height
properties is "new". This means that some browsers may still render a0
value by default, because they implemented flex layout before the value was updated and because0
is the initial value formin-width
andmin-height
in CSS 2.1. One such browser is IE11. Other browsers have updated to the newerauto
value as defined in the flexbox spec.
Revised Demo
.container {
display: flex;
}
.col {
min-height: 200px;
padding: 30px;
word-break: break-word
}
.col1 {
flex: 1;
background: orange;
font-size: 80px;
min-width: 0; /* NEW */
}
.col2 {
flex: 3;
background: yellow
}
.col3 {
flex: 4;
background: skyblue
}
.col4 {
flex: 4;
background: red
}
<div class="container">
<div class="col col1">Lorem ipsum dolor</div>
<div class="col col2">Lorem ipsum dolor</div>
<div class="col col3">Lorem ipsum dolor</div>
<div class="col col4">Lorem ipsum dolor</div>
</div>
jsFiddle
I'm finding this has bitten me repeatedly over the years for both flex and grid, so I'm going to suggest the following:
* { min-width: 0; min-height: 0; }
and then just use min-width: auto
or min-height: auto
if you need that behaviour.
In fact, throw in box-sizing as well to make all layout more sane:
* { box-sizing: border-box; min-width: 0; min-height: 0; }
Does anyone know if there are any odd consequences? I've not encountered anything in several years of using a mix of the above. In fact, I can't think of any cases where I'd want to layout from content outwards to the flex/grid, rather than flex/grid inwards to the content --- and surely if they exist, they're rare. So this feels like a bad default. But maybe I'm missing something?