2

I need to make an image take the maximum size (taking max width or max height) in a flex container.

Since the parent container doesn't have a fixed width and height, I can't use max-width and max-height and flex:1 is not working either.

Here is an example of the problem : https://jsfiddle.net/vb26u0e5/2/

I would like the image to take automaticaly all the available green space (remove the width: 40px; line 20).

#mainContainer {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  color: white;
}

#imageContainer {
  flex: 1;
  display: flex;
  justify-content: space-between;
  background-color: green;
}

#image {
  width: 40px;
}

#previous,
#next {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 25px;
  padding: 0 10px;
  background-color: purple;
}

#title,
#footer {
  text-align: center;
}

#title {
  background-color: blue;
}

#footer {
  background-color: red;
}
<div id="mainContainer">
  <div id="title">TITLE</div>
  <div id="imageContainer">
    <div id="previous">&lt;</div>
    <img id="image" src="https://via.placeholder.com/1920x1080" />
    <div id="next">&gt;</div>
  </div>
  <div id="footer">FOOTER</div>
</div>
Rafael Herscovici
  • 16,558
  • 19
  • 65
  • 93
JeanBlaguin
  • 97
  • 1
  • 1
  • 9

3 Answers3

2

Add this to your code:

#image {
  width: 40px;
  flex-grow: 1; /* new */
}

Normally, you would be able to use flex-basis (which is equivalent to width, in this case), and do some like this:

#image {
  flex: 1; /* fg:1, fs:1, fb:0 */
}

OR

#image {
  flex: 1 0 40px; 
}

However, some browsers have a bug which causes them to ignore flex-basis in nested flex containers. So the width / flex-grow combination is a clean workaround.

For more details see the "Browser Bugs" section in my answer here:


The demo below covers the issue answered above, plus height issues – aspect ratio and vertical scroll – by wrapping the image in a div and using absolute positioning and object-fit on the image.

Tested in Chrome, Firefox and Edge.

#mainContainer {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  color: white;
}

#imageContainer {
  flex: 1;
  display: flex;
  justify-content: space-between;
  background-color: green;
}

#image {
  flex-grow: 1;
  position: relative;
}

img {
  position: absolute;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

#previous,
#next {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 25px;
  padding: 0 10px;
  background-color: purple;
}

#title,
#footer {
  text-align: center;
}

#title {
  background-color: blue;
}

#footer {
  background-color: red;
}
<div id="mainContainer">
  <div id="title">TITLE</div>
  <div id="imageContainer">
    <div id="previous">&lt;</div>
    <div id="image">
      <img src="https://pixabay.com/get/52e3dc454f50a414f6d1867dda6d49214b6ac3e45657744e7d2b72dc90/oldtimer-4396528_1920.jpg" />
    </div>
    <div id="next">&gt;</div>
  </div>
  <div id="footer">FOOTER</div>
</div>

jsFiddle

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • The ```width:40px```was to remove, just to show the green space. It almost works on Firefox (but height is too large and cause a scroll). It doesn't work at all on Chrome. – JeanBlaguin Aug 14 '19 at 13:16
  • 1
    Understood. I just used it to demo `flex-basis`. You can remove it. I'm also posting a full demo, that solves for width and height. – Michael Benjamin Aug 14 '19 at 13:17
  • 1
    It's working great ! Thank you very much for your help ! – JeanBlaguin Aug 14 '19 at 13:32
  • 1
    @JeanBlaguin, generally speaking, try to avoid making images into flex / grid items. Browsers can't yet reliably handle images in a flex / grid formatting context (risk of buggy behavior is high). Wrap the image in a div, making the div the item, and keeping the image in a block formatting context. – Michael Benjamin Aug 14 '19 at 13:37
0

use object-fit property to specify how the image should be resized to fit its container. I have set it to object-fit: cover which will cut off the sides of the image, preserving the aspect ratio, and also filling in the space. Also use flex-grow:1 to fill the 'green' space.

#mainContainer {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  color: white;
}

#imageContainer {
  display: flex;
  justify-content: space-between;
  background-color: green;
}

#image {
  object-fit: cover;
  flex-grow: 1;
  height: 100%;
  overflow: hidden;
}

#previous,
#next {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 25px;
  padding: 0 10px;
  background-color: purple;
}

#title,
#footer {
  text-align: center;
}

#title {
  background-color: blue;
}

#footer {
  background-color: red;
}
<div id="mainContainer">
  <div id="title">TITLE</div>
  <div id="imageContainer">
    <div id="previous">&lt;</div>
    <img id="image" src="https://via.placeholder.com/1920x1080" />
    <div id="next">&gt;</div>
  </div>
  <div id="footer">FOOTER</div>
</div>
Soothran
  • 1,233
  • 4
  • 14
0

You can calc the width based on Vertical Width (100vw) & remove the padding of your PREV/NEXT Something like this?

#mainContainer {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  color: white;
}

#imageContainer {
  flex: 1;
  display: flex;
  justify-content: space-between;
  background-color: green;
}

#image {
  width: calc(100vw - 50px);
  height: 100vh;
}

#previous,
#next {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 25px;
  padding: 0 10px;
  background-color: purple;
}

#title,
#footer {
  text-align: center;
}

#title {
  background-color: blue;
}

#footer {
  background-color: red;
}
<div id="mainContainer">
  <div id="title">TITLE</div>
  <div id="imageContainer">
    <div id="previous">&lt;</div>
    <img id="image" src="https://via.placeholder.com/1920x1080" />
    <div id="next">&gt;</div>
  </div>
  <div id="footer">FOOTER</div>
</div>
Rafael Herscovici
  • 16,558
  • 19
  • 65
  • 93
  • The Header and footer content is variable so I'm afraid it's not an option. I'd like the image to size automatically – JeanBlaguin Aug 14 '19 at 13:18