44

So I want an img to be displayed

  • as big as possible (filling the width when it is landscape / height when it is portrait)
  • no crop
  • no skew or stretch (original aspect ratio)
  • centred both vertically and horizontally

Also, the image's original size is not known.

I've tried quite a few different options for this, including a flexbox one (to get the vertical center), but nothing seems to tick all the boxes.

Ideally I'd like this to be an all CSS solution of course, but I have been looking into some JS as well.

Thanks

suryanaga
  • 3,728
  • 11
  • 36
  • 47

5 Answers5

88

To center it, you can use the technique shown here: Absolute centering.

To make it as big as possible, give it max-width and max-height of 100%.

To maintain the aspect ratio (even when the width is specifically set like in the snippet below), use object-fit as explained here.

.className {
    max-width: 100%;
    max-height: 100%;
    bottom: 0;
    left: 0;
    margin: auto;
    overflow: auto;
    position: fixed;
    right: 0;
    top: 0;
    -o-object-fit: contain;
    object-fit: contain;
}
<img src="https://i.imgur.com/HmezgW6.png" class="className" />

<!-- Slider to control the image width, only to make demo clearer !-->
<input type="range" min="10" max="2000" value="276" step="10" oninput="document.querySelector('img').style.width = (this.value +'px')" style="width: 90%; position: absolute; z-index: 2;" >
Itay
  • 16,601
  • 2
  • 51
  • 72
  • 1
    Awesome, thanks, this works perfectly. I think I didn't try this because I thought it would stretch it, but it's cool how those max settings work. – suryanaga Aug 28 '13 at 14:24
  • The whole idea is that `max` only limits from above. – Itay Aug 28 '13 at 14:25
  • 8
    Also add `zoom: 10` (10 should be enough) if you want a smaller image to stretch to container's border. – Pandaiolo Oct 22 '13 at 14:37
  • 3
    If Image is small than screen it doesn't stretch to screen size.? what can i do to achieve that? – Straw Hat Jan 29 '14 at 08:48
  • 2
    @Pandaiolo: zoom is nonsense, it's not valid css property. And it does not work (in FF). – Pointer Null Jan 29 '14 at 15:46
  • @Pointer Null yep, I realized that later, thanks for pointing it out – Pandaiolo Jan 30 '14 at 11:43
  • To make it full width for smaller image, all you have to do is to add `min-width: 100%;` and it will stretch smaller images – John Max Jul 21 '16 at 06:45
  • yeah, i have to detect portrait / landscape and add min-width or min-height based on it – csomakk Apr 03 '17 at 11:05
  • 1
    `max-height` and `max-width` do not increase the dimensions of an image. If your images are small, they will stay small. The OP asked for images that scale to fill the viewport. – Xavier Sep 26 '19 at 10:02
5

You could use a div with a background image instead and this CSS3 property:

background-size: contain

You can check out an example on:

https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Scaling_background_images#contain

To quote Mozilla:

The contain value specifies that regardless of the size of the containing box, the background image should be scaled so that each side is as large as possible while not exceeding the length of the corresponding side of the container.

However, keep in mind that your image will be upscaled if the div is larger than your original image.

dcro
  • 13,294
  • 4
  • 66
  • 75
  • 1
    Can't do this as the image has to be loaded into the HTML with PHP. – suryanaga Aug 28 '13 at 14:21
  • 1
    This is a great option for various applications because you can get some neat effects with transitions. The one drawback in using this for the OP's request is that you lose your `img` markup. If you are like me, then you want your images for SEO, and all the cool things that social media does with your pages when embedding links from your site. – Xavier Sep 26 '19 at 10:22
2

I have come to point out the answer nobody seems to see here. You can fullfill all requests you have made with pure CSS and it's very simple. Just use Media Queries. Media queries can check the orientation of the user's screen, or viewport. Then you can style your images depending on the orientation.

Just set your default CSS on your images like so:

img {
   width:auto;
   height:auto;
   max-width:100%;
   max-height:100%;
}

Then use some media queries to check your orientation and that's it!

@media (orientation: landscape) { img { height:100%; } }
@media (orientation: portrait) { img { width:100%; } }

You will always get an image that scales to fit the screen, never loses aspect ratio, never scales larger than the screen, never clips or overflows.

To learn more about these media queries, you can read MDN's specs.

Centering

To center your image horizontally and vertically, just use the flex box model. Use a parent div set to 100% width and height, like so:

div.parent {
   display:flex;
   position:fixed;
   left:0px;
   top:0px;
   width:100%;
   height:100%;
   justify-content:center;
   align-items:center;
}

With the parent div's display set to flex, the element is now ready to use the flex box model. The justify-content property sets the horizontal alignment of the flex items. The align-items property sets the vertical alignment of the flex items.

Conclusion

I too had wanted these exact requirements and had scoured the web for a pure CSS solution. Since none of the answers here fulfilled all of your requirements, either with workarounds or settling upon sacrificing a requirement or two, this solution really is the most straightforward for your goals; as it fulfills all of your requirements with pure CSS.

EDIT: The accepted answer will only appear to work if your images are large. Try using small images and you will see that they can never be larger than their original size.

Xavier
  • 109
  • 9
1

After a lot of trial and error I found this solved my problems. This is used to display photos on TVs via a browser.

  • It Keeps the photos aspect ratio
  • Scales in vertical and horizontal
  • Centers vertically and horizontal
  • The only thing to watch for are really wide images. They do stretch to fill, but not by much, standard camera photos are not altered.

    Give it a try :)

*only tested in chrome so far

HTML:

<div class="frame">
  <img src="image.jpg"/>
</div>

CSS:

.frame {
  border: 1px solid red;

  min-height: 98%;
  max-height: 98%;
  min-width: 99%;
  max-width: 99%;

  text-align: center;
  margin: auto;
  position: absolute;
}
img {
  border: 1px solid blue;

  min-height: 98%;
  max-width: 99%;
  max-height: 98%;

  width: auto;
  height: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}
  • This approach will skew the image, change the aspect ratio. The OP asked to maintain aspect ratio. – Xavier Sep 26 '19 at 10:04
-2
yourimg {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
}

and make sure there is no parent tags with position: relative in it

Vladimir
  • 377
  • 1
  • 6