1

I have an image in a flex container (let's call it child). The container itself has flex: 1 because it also belongs to a flex parent with flex-direction: column and child behaves as expected (takes 100% height of parent) before introducing the image situation.

On adding an image to child, the image extends child to accommodate its height, effectively child pushing parent.

Using object-fit: cover on the image could not help in this situation!

Looks like this is normal behaviour in Chrome, Firefox, and Safari.

Here's the weird part tho: adding a height property to child fixes the issue on Chrome and Safari but not Firefox. This height's value doesn't matter much as long as it's not greater than the computed height of child - child is contained to 100% height of parent together with the image - even if the height value of child is set to 1px. Surprisingly height: 100% on child doesn't produce the same behaviour.

Any ideas around this will be much appreciated. My goal is to make the image always take up 100% of child - regardless of the width of the viewport.

Here's some code for illustration

#parent {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

#child {
  flex: 1;
  height: 1px;
  /* the weird hack for chrome and safari - ff ignores it */
}

#child img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div id="parent">
  <div id="child">
    <img src="https://i.picsum.photos/id/1005/400/1000.jpg" />
  </div>
</div>

I also added some images for more context. These are crops of the entire page. The first image is from a smaller viewport (width shared with devtools) and the second from the entire page (devtools hidden). The second image shows that the image has extended child to eventually push the container with a green background beyond the fold - causing a scrollbar to appear.

child is the image wrapper, and parent is the component with a white background and some padding. You realize parent has a sibling (green background) and their parent (container with a green border and border radius) has a display: grid and grid-template-rows: 1fr auto;.

It should also be noted that the most top-level element has a height of 100vh and all its children are rendered within that. Essentially there should not be a scrollbar.

I hope you get the idea.

small viewport (width shared with devtools)

full viewport (devtools hidden)

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
kawerewagaba
  • 1,107
  • 2
  • 15
  • 21
  • try `min-height:0` for child – Temani Afif Feb 25 '20 at 09:43
  • No effect @TemaniAfif. Why do you think that would work tho? – kawerewagaba Feb 25 '20 at 09:47
  • https://stackoverflow.com/a/36247448/8620333 – Temani Afif Feb 25 '20 at 09:47
  • There's truth in that link @TemaniAfif. Apparently `min-height: 0` works on `grid` containers as well. However, I noticed it's supposed to be applied onto the `top-level` parent and also automatically truncates anything that overflows - as long as the full height of the image has been accommodated. – kawerewagaba Feb 25 '20 at 10:04
  • That behaviour is not desirable in my situation. The `image` should behave itself. – kawerewagaba Feb 25 '20 at 10:10
  • 1
    Do you really need an ? Sounds like what you wish to achieve ("to make the image always take up 100% of child - regardless of the width of the viewport") could be made setting a background-image to that #child instead, something like `background: url('imageURL') center / auto 100% no-repeat` – Kaiido Feb 25 '20 at 10:19
  • Yeah, I do @Kaiido. I didn't mention I'm using `React` to render a `scrollable` list/component (`child` in our context) of images, by passing the `url` as a `prop` to `src`. I may have to share more context for the problem to be better understood. Let me prep some screenshots. – kawerewagaba Feb 25 '20 at 10:56
  • Looks like everyone is shying away... – kawerewagaba Feb 25 '20 at 20:11
  • I will repeat my first comment: considering the code you shared `min-height: 0` fixes your issue. Replace height:1px with it on the snippet your shared and it will work – Temani Afif Feb 27 '20 at 15:18
  • fro cross browser compatibility you can use background image instead of image tag. Support for background image is found pretty good. – 9841pratik Feb 28 '20 at 11:12
  • have you tried to give the child instead of 1px to inherit – godfather Feb 28 '20 at 15:38
  • Will the images always be the same size and aspect ratio? – greg Feb 28 '20 at 16:35
  • Did you try setting 100% height to the child. https://codepen.io/rohinikumar4073/pen/MWwmZyX – vishnu sandhireddy Feb 28 '20 at 17:17
  • It's not that the `image` is not *behav[ing] itself`. As the link provided by @TemaniAfif says, you're encountering a behaviour related to the default minimum size of flex items, not the image itself. – Richard Mar 02 '20 at 05:09
  • @greg yeah, all the images shall be identical – kawerewagaba Mar 02 '20 at 20:39

2 Answers2

2

Is this what you are looking to do? You can also see it here: https://codepen.io/teanbiscuits/pen/GRJmPgo

#parent {
  height: 100vh;
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr auto;
  border:2px solid green;
  border-radius:20px;
  overflow:hidden;
}

#child {
  position:relative;
}

#child img {
  position:absolute;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

#text {
  background-color:green;
}
<div id="parent">
  <div id="child">
    <img src="https://i.picsum.photos/id/1005/400/1000.jpg" />
  </div>
  <div id="text">
    <h2>some title here</h2>
    <p>Some description here</p>
  </div>
</div>
greg
  • 164
  • 2
  • 11
  • you won the bounty! I love the way you approached this - making the image behave, using `absolute` positioning. – kawerewagaba Mar 02 '20 at 21:23
  • Thanks! It's an approach I use often. Depending on how you want the image to appear and if it's a product image or not you can change "object-fit: contain;" to "object-fit: cover;" – greg Mar 03 '20 at 08:19
0

Please try this. Just select preferred object-fit.

html, body{
  height: 100%;
  margin: 0;
  padding: 0;
}
#parent {
  height: calc(100vh - 20px);
  display: flex;
  padding: 10px;
  flex-direction: column;
}

#child {
  flex: 1;
  text-align: center;
  overflow: hidden;
}

#child img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
<div id="parent">
  <div id="child">
    <img src="https://i.picsum.photos/id/1005/400/1000.jpg" />
  </div>
  <div id="text">
    <h2>Some title here</h2>
    <p>Some description here</p>
  </div>
</div>
Dmytro Cheglakov
  • 744
  • 4
  • 14