Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

max-width doesn't work in flexbox

Tags:

html

css

flexbox

I'm trying to get a two-column flexbox with some content on the left, and the remaining space taken up by an image. The image should be centred in the remaining space and shrink-to-fit. Here's what I've got:

* {
    box-sizing: border-box;
}
.small_margin {
    margin: 5px;
}
.small_padding {
    padding: 5px;
}

.red {
    background: #faa;
}
.blue {
    background: #aaf;
}
.green {
    background: #afa;
}

.small_container {
    width: 500px;
    display: flex;
    flex-direction: row;
}

.large_container {
    width: 900px;
    display: flex;
    flex-direction: row;
}

.image {
    max-width: 100%; /* Why does this not work? If you change it to a fixed value (not a percentage) it works. */
    max-height: 20em;
}

.image_holder {
    flex-grow: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}
    
<div class="red large_container">
    <div class="blue small_margin small_padding" style="width: 120px;">
        <h1>This Works</h1>
        <p>This is what I want when there is space for the full-size image (restricted to its max-height). It should be centred in the div to the right.</p>
        <p>This is good.</p>             
    </div>
    <div class="green small_margin image_holder">
        <img class="image" src="http://www.gstatic.com/webp/gallery/1.jpg"/>
    </div>
</div>

<br>

<div class="red small_container">
    <div class="blue small_margin small_padding">
        <h1>This Doesn't</h1>
        <p>There is now no longer space for the image but instead of reducing its size to 100% of its parent div it just overflows.</p>              
    </div>
    <div class="green small_margin image_holder">
        <img class="image" src="http://www.gstatic.com/webp/gallery/1.jpg"/>
    </div>
</div>

As you can see, the image overflows the flexbox and isn't shrunk-to-fit by the max-width: 100%. Presumably 100% doesn't actually mean "100% the width of the parent div"?

Anyway, is there any way to make this work?

like image 731
Timmmm Avatar asked Aug 12 '15 13:08

Timmmm


Video Answer


1 Answers

The image has max-width: 100%. That means that it shouldn't be wider than its parent (the flex item). And this works.

Instead, the problem is that the flex item overflows the flex container. That happens because Flexbox introduces auto as the initial value of min-width. When overflow is visible, that auto forces the flex item to grow so that its content doesn't overflow.

Therefore, you can use min-width: 0.

.image_holder {
  min-width: 0;
}

* {
  box-sizing: border-box;
}
.small_margin {
  margin: 5px;
}
.small_padding {
  padding: 5px;
}
.red {
  background: #faa;
}
.blue {
  background: #aaf;
}
.green {
  background: #afa;
}
.small_container {
  width: 500px;
  display: flex;
  flex-direction: row;
}
.large_container {
  width: 900px;
  display: flex;
  flex-direction: row;
}
.image {
  max-width: 100%; /* Why does this not work? If you change it to a fixed value (not a percentage) it works. */
  max-height: 20em;
}
.image_holder {
  flex-grow: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
}
<div class="red large_container">
  <div class="blue small_margin small_padding" style="width: 120px;">
    <h1>This Works</h1>
    <p>This is what I want when there is space for the full-size image (restricted to its max-height). It should be centred in the div to the right.</p>
    <p>This is good.</p>             
  </div>
  <div class="green small_margin image_holder">
    <img class="image" src="http://www.gstatic.com/webp/gallery/1.jpg"/>
  </div>
</div>
<br>
<div class="red small_container">
  <div class="blue small_margin small_padding">
    <h1>This Doesn't</h1>
    <p>There is now no longer space for the image but instead of reducing its size to 100% of its parent div it just overflows.</p>              
  </div>
  <div class="green small_margin image_holder">
    <img class="image" src="http://www.gstatic.com/webp/gallery/1.jpg"/>
  </div>
</div>

Then the image won't overflow the flex container. However, it won't mantain its aspect ratio.

To fix that, you can use object-fit:

.image {
  object-fit: contain;
}

* {
  box-sizing: border-box;
}
.small_margin {
  margin: 5px;
}
.small_padding {
  padding: 5px;
}
.red {
  background: #faa;
}
.blue {
  background: #aaf;
}
.green {
  background: #afa;
}
.small_container {
  width: 500px;
  display: flex;
  flex-direction: row;
}
.large_container {
  width: 900px;
  display: flex;
  flex-direction: row;
}
.image {
  max-width: 100%; /* Why does this not work? If you change it to a fixed value (not a percentage) it works. */
  max-height: 20em;
  object-fit: contain;
}
.image_holder {
  flex-grow: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
}
<div class="red large_container">
  <div class="blue small_margin small_padding" style="width: 120px;">
    <h1>This Works</h1>
    <p>This is what I want when there is space for the full-size image (restricted to its max-height). It should be centred in the div to the right.</p>
    <p>This is good.</p>             
  </div>
  <div class="green small_margin image_holder">
    <img class="image" src="http://www.gstatic.com/webp/gallery/1.jpg"/>
  </div>
</div>
<br>
<div class="red small_container">
  <div class="blue small_margin small_padding">
    <h1>This Doesn't</h1>
    <p>There is now no longer space for the image but instead of reducing its size to 100% of its parent div it just overflows.</p>              
  </div>
  <div class="green small_margin image_holder">
    <img class="image" src="http://www.gstatic.com/webp/gallery/1.jpg"/>
  </div>
</div>
like image 159
Oriol Avatar answered Sep 17 '22 12:09

Oriol