How to make an image fill a flex item with flex-grow?

Viewed 5049

I've read through all existing solutions in which images could fill the containing divs but I haven't found a solution for filling a div without a static dimension, such as divs that only have been laid out by flex-grow.

Currently the image will destroy the flex-grow proportions I have set on the container. I want the img to just fill the div and not stretch the div out.

As much as possible I don't want to inline style.

Is there an existing polyfill or solution to this?

.container {
  display: flex;
  min-height: 300px;
  width: 500px;
  flex: 1;
}

.sub-container {
  flex: 1;
  display: flex;
  flex-direction: row;
}

.sub-container > div {
  flex-grow: 1;
}

.first-container {
  background-color: blue;
}

.second-container {
  background-color: yellow;
}

.second-container>img {
  max-height: 100%;
  max-width: 100%;
  object-fit: scale-down;
}
<div class="container">
  <div class="sub-container">
    <div class="first-container">
      A
    </div>
    <div class="second-container">
      <img src="https://internationalbarcodes.net/wp-content/uploads/2017/04/QR%20code%20example.jpg" />
    </div>
  </div>
</div>

http://jsfiddle.net/jojonarte/tu3nbw4q/

2 Answers

You have this in your code:

.sub-container > div {
  flex-grow: 1;
}

Okay, that defines flex-grow.

But you haven't defined flex-basis. As a result, flex-basis keeps its default value, which is: auto (i.e., content-defined).

That's what you're seeing your layout: A flex item that is being sized by the content.

In other words, because the natural dimensions of the image are so large (in comparison to the size of the container), the image is taking up all free space and flex-grow is having no effect (it has no free space to distribute).

As a solution, add this to the rule:

.sub-container > div {
  flex-grow: 1;
  flex-basis: 0; /* new */
}

or, more efficiently:

.sub-container > div {
  flex: 1; /* fg:1, fs:1, fb:0 */
}

revised fiddle

.container {
  display: flex;
  min-height: 300px;
  width: 500px;
}

.sub-container {
  flex: 1;
  display: flex;
  flex-direction: row;
}

/* ADJUSTMENT HERE */
.sub-container > div {
  flex: 1;
}

.first-container {
  background-color: blue;
}

.second-container {
  background-color: yellow;
}

.second-container>img {
  max-height: 100%;
  max-width: 100%;
  object-fit: scale-down;
}
<div class="container">
  <div class="sub-container">
    <div class="first-container">A</div>
    <div class="second-container">
      <img src="https://internationalbarcodes.net/wp-content/uploads/2017/04/QR%20code%20example.jpg" />
    </div>
  </div>
</div>

More information:

Use background-image instead use img tag and use background-size: 100% 100%;:

See fiddle

.container {
  display: flex;
  min-height: 300px;
  width: 500px;
  flex: 1;
}

.sub-container {
  flex: 1;
  display: flex;
  flex-direction: row;
}

.sub-container>div {
  flex-grow: 1;
}

.first-container {
  background-color: blue;
}

.second-container {
      background: url(https://internationalbarcodes.net/wp-content/uploads/2017/04/QR%20code%20example.jpg);
    background-repeat: no-repeat;
    background-size: 100% 100%;
  
}
<div class="container">
  <div class="sub-container">
    <div class="first-container">
      A
    </div>
    <div class="second-container">

    </div>
  </div>

</div>

Related