Prevent CSS3 Flex-Shrink from Crushing Content

How to keep a flex item from overflowing due to its text?

UPDATE

Adding code that works:

.container {    display: -webkit-flex; }
.container>div:first-child{ white-space:nowrap; -webkit-order:1; -webkit-flex: 0 1 auto; /*important*/ text-overflow: ellipsis; overflow:hidden; min-width:0; /* new algorithm overrides the width calculation */}
.container > div:last-child { -webkit-flex: 1; -webkit-order:2; background: red; -webkit-flex:1 0 auto; /*important*/}.container > div:first-child:hover{ white-space:normal;}
<div class="container">    <div>foo barfoo bar</div>    <div>foo bar</div></div>
<div class="container"> <div>foo barfoo barfoo barfoo barfoo barfoo barfoo bar foo barfoo barfoo barfoo barfoo barfoo barfoo bar foo barfoo barfoo barfoo barfoo barfoo barfoo bar</div> <div>foo bar</div></div><div class="container"> <div>foo barfoo bar</div> <div>foo bar</div></div>
<div class="container"> <div>foo barfoo barfoo barfoo barfoo barfoo barfoo bar foo barfoo barfoo barfoo barfoo barfoo barfoo bar foo barfoo barfoo barfoo barfoo barfoo barfoo bar</div> <div>foo bar</div></div><div class="container"> <div>foo barfoo bar</div> <div>foo bar</div></div>

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, except visible)

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
the min-width and min-height properties defined in CSS 2.1.

With regard to the auto value...

On a flex item whose overflow is visible in the main axis, when specified on the flex item’s main-axis min-size property, specifies an automatic minimum size. It otherwise computes to 0.

In other words:

  • The min-width: auto and min-height: auto defaults apply only when overflow is visible.
  • If the overflow value is not visible, the value of the min-size property is 0.
  • Hence, overflow: hidden can be a substitute for min-width: 0 and min-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 the 0 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 Chrome

  • IE11

    As noted in the spec, the auto value for the min-width and min-height properties is "new". This means that some browsers may still render a 0 value by default, because they implemented flex layout before the value was updated and because 0 is the initial value for min-width and min-height in CSS 2.1. One such browser is IE11. Other browsers have updated to the newer auto 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>

CSS Flexbox Image Shrink

If instead of img you use background-image for div.picture-container, you can use cover or contain on the background to maintain aspect ratio (fiddle):

HTML:

<div class="container">
<div class="title-container">
<h1>Title</h1>
</div>
<div class="picture-container" style="background-image: url(http://i.imgur.com/D08iV30.jpg)">
</div>
<div class="button-container">
<span>button</span>
</div>
</div>

CSS

.container {
border: 1px solid black;
height: 300px;
width: 300px;
display: flex;
flex-direction: column;
}
.title-container {
flex-shrink: 0;
}
.button-container {
flex-shrink: 0;
}
.picture-container {
flex: 1;
background-size: cover; /** you can use contain if you want to prevent image cropping **/
background-repeat: no-repeat;
}

How do I prevent 100% width images from expanding to the body size when inside a flex container?

#shop-panels div.panel {
flex: 0 1 25%;
}
#shop-panels div.panel .content img {
width: 100%;
}

http://www.cssdesk.com/tjsDx


Why this works:

flex: 1 0 auto;

...in your code, means:

flex-grow: 1;
flex-shrink: 0;
flex-basis: auto;

...which is clearly not what you want. If you don't want your flex-items to grow past 25%, you need to set it to:

flex: 0 1 25%;

or, alternatively, set the flex items max-width to:

max-width: calc(25% - 1em); /* subtracting margins */

Sidenote: don't work on prefixed CSS. Use only the clean syntax and use autoprefixer at the end. For maximum compatibility, set > 0% in box below it.

Can CSS3 Flex take only integer values?

According to the Mozilla Docs, https://developer.mozilla.org/en-US/docs/Web/CSS/flex , it takes a number value - which includes non-integers according to the MDN docs. All valid number values:

12          A raw <integer> is also a <number>
4.01 A positive non-integer <number>
-456.8 Negative non-integer <number>
0.0 Zero
+0.0 Zero, with a leading +
-0.0 Zero, with a leading - (Though strange, this is an allowed value)
.60 Digits are optional before the dot
10e3 The scientific notation is allowed
-3.4e-2 Most complex case of scientific notatio

Flex item is squashed by it's own margin

Add flex-shrink: 0 to span, as the problem is that item has by default flex-shrink: 1, which means it determines how much the flex item will shrink relative to the rest of the flex items in the flex container when there isn’t enough space on the row.