Centering and scaling an image in Flexbox

With am <img> (of unknown sizes) inside the container set to display:flexbox , is it possible to satisfy the following criteria:

  • If the dimensional width of the image is less than the width of the container, it is horizontally centered inside the container.

enter image description here

  1. If the height of the image is less than the height of the container, it is vertically centered with the container.

enter image description here

  1. If the image is wider than the width of the container, the image is scaled to the width of the container.

enter image description here

  1. If the height of the image carrier is greater than the height of the container, the image is scaled to the height of the container.

enter image description here

I noticed a big discrepancy between the way Chrome and Firefox handle images that are flexbox children. Chrome is halfway through, but displays the image vertically. Firefox is halfway through, but displays image horizontally: Codepen

 body, html { width: 100%; height: 100%; margin: 0; padding: 0; } .Container { height: 100%; width: 100%; background: red; display: flex; justify-content: center; align-items: center; } img{ max-height: 100%; max-width: 100%; } 
 <div class="Container"> <img src="http://d13rap2ac6f4c9.cloudfront.net/image_assets/quarry_medium.jpg?1410945487"> </div> 

This is the closest I can get a Codepen that does not work on 4 .:

 body, html { width: 100%; height: 100%; margin: 0; padding: 0; } .Container { height: 100%; width: 100%; background: red; display: flex; justify-content: center; align-items: center; } .ImageWrapper { max-height: 100%; max-width: 100%; } img{ max-height: 100%; max-width: 100%; width: 100%; height: auto; } 
 <div class="Container"> <div class="ImageWrapper"> <img src="http://d13rap2ac6f4c9.cloudfront.net/image_assets/quarry_medium.jpg?1410945487"> </div> </div> 

I know that this kind of behavior was previously impossible without JavaScript, but I am surprised that this is not possible with flexbox.

Note. I am not looking for a solution for JavaScript or a solution that does not yet work in modern browsers.

In response to David Mann's answer, here is the previous example using object-fit Codepen .

 body, html { width: 100%; height: 100%; margin: 0; padding: 0; } .Container { height: 100%; width: 100%; background: red; display: flex; justify-content: center; align-items: center; } img{ max-height: 100%; max-width: 100%; object-fit: contain; } 
 <div class="Container"> <img src="http://d13rap2ac6f4c9.cloudfront.net/image_assets/quarry_medium.jpg?1410945487"> </div> 

Here is Codepen using polyfill . Appears to work fine in IE10, but broken in IE11.

+6
source share
2 answers

CSS is catching up. It no longer has support , but object-fit: contain does exactly what you want (EDIT 11/17: Edge now has partial support, which makes IE11 the only browser without support). Just put this in your css rule for img and change max-width: 100% and max-height: 100% to width: 100% and height: 100% . Here is the codepen .

 .Container { height: 100vh; width: 100vw; background: red; display: flex; justify-content: center; align-items: center; } img { height: 100%; width: 100%; object-fit: contain; } body { margin: 0; } 
 <div class="Container"> <img src="https://unsplash.it/2000/1500"> </div> 

If IE does not support object-fit , this is a transaction breaker, then there is javascript polyfill for it. Here is a bit more about this from css-tricks .

You can also get the same effect with background-image , but it just looks like a cheat.

Just add this to .Container :

 background-image: url(http://d13rap2ac6f4c9.cloudfront.net/image_assets/quarry_medium.jpg?1410945487); background-size: contain; background-repeat:no-repeat; background-position: center; 

Then completely remove the img tag. The effect is the same, but without the actual element in .Container . It should be noted that with this method display: flex is not even required.

Here is another codepen for this method.

 .Container { height: 100vh; width: 100vw; background: red; background-image: url(https://unsplash.it/2000/1500); background-size: contain; background-repeat: no-repeat; background-position: center; } body { margin: 0; } 
 <div class="Container"> </div> 

the support here is much better and there are even more things you can play with. Once again, here is an almanac entry from css tricks

+8
source

Approach 1: using a CSS table cell, see the following demos.

 div { border: 1px solid red; width: 100px; height: 100px; display: table-cell; text-align: center; vertical-align: middle; } img { max-width: 100%; max-height: 100%; vertical-align: middle; } 
 <div><img src="//dummyimage.com/75x50" /></div> <div><img src="//dummyimage.com/50x75" /></div> <div><img src="//dummyimage.com/300x200" /></div> <div><img src="//dummyimage.com/200x300" /></div> <div><img src="//dummyimage.com/200x200" /></div> 

Approach 2: using the built-in unit and see notes below.

 div { border: 1px solid red; width: 100px; height: 100px; display: inline-block; text-align: center; vertical-align: top; } div:before { content: ""; height: 100%; display: inline-block; vertical-align: middle; } img { max-width: 100%; max-height: 100%; vertical-align: middle; } 
 <div><img src="//dummyimage.com/75x50" /></div> <div><img src="//dummyimage.com/50x75" /></div> <div><img src="//dummyimage.com/300x200" /></div> <div><img src="//dummyimage.com/200x300" /></div> <div><img src="//dummyimage.com/200x200" /></div> 

Additional notes: set font-size:0; in the parent container when there is empty space in it and then reset to font-size:16px; or so on in the inner container if there is text content inside. Follow this for more information - fooobar.com/questions/6427 / ...

+2
source

All Articles