How can I fill a div with an image while keeping it proportional?
Asked Answered
A

19

214

I found this thread — How do you stretch an image to fill a <div> while keeping the image's aspect-ratio? — that is not entirely the thing that I want.

I have a div with a certain size and an image inside of it. I want to always fill-out the div with the image regardless if the image is landscape or portrait. And it doesn't matter if the image is cut-off (the div itself has overflow hidden).

So if the image is portrait I want the width to be 100% and the height:auto so it stays in proportion. If the image is landscape I want the height to be 100% and the width to be auto`. Sounds complicated right?

<div class="container">
   <img src="some-image.jpg" alt="Could be portrait or landscape"/>
</div>

Since I don't know how to do it I simply created a quick image of what I mean. I can't even properly describe it.

enter image description here

So, I guess I'm not the first one asking this. However I couldn't really find a solution to this. Maybe there is some new CSS3 way of doing this - I'm thinking of flex-box. Any idea? Maybe it's even easier than I expect it to be?

African answered 3/1, 2013 at 15:54 Comment(0)
P
248

If I correctly understand what you want, you may leave the width and height attributes off the image to maintain aspect ratio and use flexbox to do the centering for you.

.fill {
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden
}
.fill img {
    flex-shrink: 0;
    min-width: 100%;
    min-height: 100%
}
<div class="fill">
    <img src="https://picsum.photos/id/237/320/240" alt="" />
</div>

JSFiddle here.

I tested this successfully in IE9, Chrome 31, and Opera 18. But no other browsers were tested. As always you must consider your particular support requirements.

Priedieu answered 3/12, 2013 at 2:6 Comment(5)
In IE9 the image is not centered vertically or horizontally with this method, it is aligned to the top and left. i59.tinypic.com/ouo77s.pngPostpaid
This has an issue on iPad, it appears safari stretches the image to 100% of its height but does not retain the min-width property.Scopoline
This seems to scale small images up to fill, but not down to fit. At least when I use a large image it only shows a tiny portion of it.Perambulate
To have a large image scaled down to fit, I used the following on the image: .fill img { min-height:100%; min-width: 100%; object-fit: cover; } Bacchanalia
Thank you!!! I have been searching for this. Just needed these changes to .fill img change flex-shrink to flex-shrink: 1 (or remove it) and add object-fit: cover. Basically change this css to what @PeterG said.Cusped
A
108

It's a bit late but I just had the same problem and finally solved it with object-fit: cover with the help of another stackoverflow post (https://stackoverflow.com/a/29103071).

img {
   object-fit: cover;
   width: 50px;
   height: 100px;
}

Hope this still helps somebody.

Ps: Also works together with max-height, max-width, min-width and min-height css properties. It's espacially handy with using lenght units like 100% or 100vh or 100vw to fill the container or the whole browser window.

Arteaga answered 25/8, 2016 at 16:8 Comment(5)
is this a crossbrowser solution?Greasewood
object-fit: cover; works great! Browser info (does not work in IE): css-tricks.com/almanac/properties/o/object-fit Fallback solution for IE: medium.com/@primozcigler/… MS is working on implementing it: developer.microsoft.com/en-us/microsoft-edge/platform/status/…Salol
I guess adding an object-position rule to this class will be helpful here. Just a side note.Disequilibrium
Just add width:100%; height :100%;Craigie
This was the best option for my case, as I did not want to add any special classes, display flex, background-image etc. Thank you!Nejd
W
19

This should do it:

img {
  min-width: 100%;
  min-height: 100%;
  width: auto;
  height: auto;
}
Wrongly answered 5/8, 2016 at 8:54 Comment(3)
Works pretty well for me, in my case I just required to add position:absolute and top:0 , and some z-index as wellCutis
very easy and clean solution without using fixed px for heights or width.Nicollenicolson
Thank you. It worked for me resizing an image together with grid-row-start and grid-row-endHustings
A
18

All answers below have fixed width and height, which makes solution "not responsive".

To achieve the result but keep image responsive I used following:

  1. Inside container place a transparent gif image with desired proportion
  2. Give an image tag inline css background with image you want to resize and crop
.container img{
   width: 100%;
   height: auto;
   background-size: cover;
   background-repeat: no-repeat;
   background-position: center;
}
<div class="container">
    <img style="background-image: url("https://i.imgur.com/XOmNCwY.jpg");" src="img/blank.gif">
</div> 
Afterward answered 23/7, 2018 at 21:20 Comment(2)
I used background-image for my entire design portfolio company website so that I could have background-size: cover. Now my image SEO is all messed up because background images aren't recognized by Google. I wish I had coded it another way.Cardiograph
best of all answers for my case of putting it into a cell in a grid layout. It becomes distorted from stretching horizontally but not vertically as it places blank space for the avoiding of vertical stretch (made a change for the height max-height: 100%;), including max-width:100% kept the proportions as it was originally in the image but if the window changes it does not fillAcrogen
G
12

A simple way I figured out to do this is by using object-fit: cover on the img inside the container

<div class="container"> 
  <img class="image" src="https://mymodernmet.com/wp/wp-content/uploads/2020/11/International-Landscape-Photographer-Year-PhotographER-1st-KelvinYuen-2.jpg">
</div>
.image { 
  height: 100%;
  width: 100%;
  object-fit: cover
}

.container {
  height: 100px; /*Set any dimensions you like*/
  width: 50px;
}

As far as I tested, this works regardless of the dimensions of the image to use, and this satisfies the "Best case" as you state in the question, since the result is vertically and horizontally centered.

Gruel answered 18/5, 2021 at 18:16 Comment(0)
I
8

An old question but deserves an update as now there is a way.

The correct CSS based answer is to use object-fit: cover, which works like background-size: cover. Positioning would be taken care of by object-position attribute, which defaults to centering.

But there is no support for it in any IE / Edge browsers, or Android < 4.4.4. Also, object-position is not supported by Safari, iOS or OSX. Polyfills do exist, object-fit-images seems to give best support.

For more details on how the property works, see CSS Tricks article on object-fit for explanation and demo.

Interplay answered 2/6, 2016 at 9:59 Comment(0)
C
8

You can achieve this using css flex properties. Please see the code below:

.img-container {
  border: 2px solid red;
  justify-content: center;
  display: flex;
  flex-direction: row;
  overflow: hidden;
  
}
.img-container .img-to-fit {
  flex: 1;
  height: 100%;
}
<div class="img-container">
  <img class="img-to-fit" src="https://images.pexels.com/photos/8633/nature-tree-green-pine.jpg" />
</div>
Cicatrize answered 11/9, 2018 at 17:24 Comment(1)
This works ONLY if you remove the width and height properties as alluded to in some of the other answers.Mischance
I
7

You should use the CSS property object-fit on the img tag:

<div class="container">
  <img src="some-image.jpg" style="width: 100%; height: 100%; object-fit: cover" />
</div>
Incontrollable answered 5/1, 2023 at 14:59 Comment(0)
R
5

Consider using background-size: cover (IE9+) in conjunction with background-image. For IE8-, there is a polyfill.

Rip answered 3/1, 2013 at 16:7 Comment(3)
Doesn't this require background-url? Can you elaborate more? Can this work with the <img src="" /> as stated in the question?Limpkin
@Limpkin Of course, background-size makes sense solely with background-image specified too (I've updated my answer accordingly). It does not apply to IMG elements.Rip
This is the best answer. It is simple and has good browser support. All other solutions are either very complex or not working in IE(9).Spilt
I
3

.image-wrapper{
    width: 100px;
    height: 100px;
    border: 1px solid #ddd;
}
.image-wrapper img {
    object-fit: contain;
    min-width: 100%;
    min-height: 100%;
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 100%;
}
<div class="image-wrapper">
  <img src="">
</div>
Ileana answered 12/1, 2019 at 15:13 Comment(1)
It seems in Chromium-based browsers width: auto; height: auto is not needed. This is the only answer that works in both dimensions and for both object-fit: contain and object-fit: cover.Spinoff
R
3

Here is an answer with support to IE using object-fit so you won't lose ratio. Using a simple JS snippet to detect if the object-fit is supported and then replace the img for a svg:

//ES6 version
if ('objectFit' in document.documentElement.style === false) {
  document.addEventListener('DOMContentLoaded', () => {
    document.querySelectorAll('img[data-object-fit]').forEach(image => {
      (image.runtimeStyle || image.style).background = `url("${image.src}") no-repeat 50%/${image.currentStyle ? image.currentStyle['object-fit'] : image.getAttribute('data-object-fit')}`
      image.src = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='${image.width}' height='${image.height}'%3E%3C/svg%3E`
    })
  })
}

//ES5 version
if ('objectFit' in document.documentElement.style === false) {
  document.addEventListener('DOMContentLoaded', function() {
    Array.prototype.forEach.call(document.querySelectorAll('img[data-object-fit]').forEach(function(image) {
      (image.runtimeStyle || image.style).background = "url(\"".concat(image.src, "\") no-repeat 50%/").concat(image.currentStyle ? image.currentStyle['object-fit'] : image.getAttribute('data-object-fit'));
      image.src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='".concat(image.width, "' height='").concat(image.height, "'%3E%3C/svg%3E");
    }));
  });
}
img {
  display: inline-flex;
  width: 175px;
  height: 175px;
  margin-right: 10px;
  border: 1px solid red
}


/*for browsers which support object fit */

[data-object-fit='cover'] {
  object-fit: cover
}

[data-object-fit='contain'] {
  object-fit: contain
}
<img data-object-fit='cover' src='//picsum.photos/1200/600' />
<img data-object-fit='contain' src='//picsum.photos/1200/600' />
<img src='//picsum.photos/1200/600' />

Note: There are also a few object-fit polyfills out there that will make object-fit work.

Here are a few examples:

Reliant answered 4/4, 2020 at 11:16 Comment(0)
G
2

My solution was:

<div
  style={{
    display: "flex",
    width: "100%",
    height: "100%",
  }}
>
  <img
    style={{
      minWidth: "100%",
      minHeight: "100%",
      objectFit: "cover",
    }}
    alt=""
    src={url}
  />
</div>

The above will scale up an image in order for it to cover the parent container.
If you just need to fit inside, then change objectFit to contain.

Grados answered 13/10, 2022 at 5:8 Comment(0)
B
1

Try this:

img {
  position: relative;
  left: 50%;
  min-width: 100%;
  min-height: 100%;
  transform: translateX(-50%);
}

Hope this helps!

Bullfighter answered 7/8, 2016 at 2:28 Comment(0)
C
1

You can use div to achieve this. without img tag :) hope this helps.

.img{
	width:100px;
	height:100px;
	background-image:url('http://www.mandalas.com/mandala/htdocs/images/Lrg_image_Pages/Flowers/Large_Orange_Lotus_8.jpg');
	background-repeat:no-repeat;
	background-position:center center;
	border:1px solid red;
	background-size:cover;
}
.img1{
	width:100px;
	height:100px;
	background-image:url('https://images.freeimages.com/images/large-previews/9a4/large-pumpkin-1387927.jpg');
	background-repeat:no-repeat;
	background-position:center center;
	border:1px solid red;
	background-size:cover;
}
<div class="img">	
</div>
<div class="img1">	
</div>
Cratch answered 29/11, 2017 at 9:11 Comment(0)
R
1

Another interesting way I have learned to achieve this is by making use of padding-bottom on the parent container to control the size and ratio of the image.

When you use padding-bottom: 100% on an empty container, CSS automatically fills the width by 100%. With that, you can start playing around with the padding-bottom for the height and optionally adjust the width of the parent container to create the desired aspect ratio.

The parent element must be set as relative, and the image should be absolute, covering the entire container.

Here's an example with a landscape and portrait image rendered in the same aspect ratio:

.container{
  padding-bottom: 40%;  
  position: relative;
width: 50%; //optional, use in combination with bottom padding as height
}

.container img{
  position: absolute;
  width: 100%;
  height: 100%;
  object-fit: cover;
  }
<h1>Using portrait image</h1>
<div class="container">
   <img src="https://images.pexels.com/photos/14339714/pexels-photo-14339714.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2" alt="Could be portrait or landscape"/>
</div>

<h1>Using landscape image</h1>
<div class="container">
   <img src="https://images.pexels.com/photos/16208497/pexels-photo-16208497/free-photo-of-zee-natuur-wolken-kust.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2" alt="Could be portrait or landscape"/>
</div>

Best to run the snippet in full screen.

source: https://v1.tailwindcss.com/course/locking-images-to-a-fixed-aspect-ratio

Relive answered 26/6, 2023 at 12:33 Comment(0)
A
0

Here you have my working example. I have used a trick that is setting the image as background of the div container with background-size:cover and background-position:center center

I have placed the image with width:100% and opacity:0 making it invisible. Note that I am showing my image only because I have an special interest on calling the child click event.

Please note that altought I am ussing angular it is completely irrelevant.

<div class="foto-item" ng-style="{'background-image':'url('+foto.path+')'}">
    <img class="materialboxed" ng-class="foto.picid" ng-src="{{foto.path}}" style="opacity: 0;filter: alpha(opacity=0);" width="100%" onclick="$('.materialboxed')/>
 </div>
<style>
.foto-item {
height: 75% !important;
width: 100%;
position: absolute;
top: 0;
left: 0;
overflow:hidden;
background-size: cover;
background-position: center center;
}
</style>

The result is the one that you define as optimal in all cases

Actinon answered 26/5, 2016 at 12:47 Comment(0)
L
0

The CSS object-fit: cover and object-position: left center property values now address this issue.

Lesseps answered 8/6, 2018 at 7:46 Comment(0)
N
0

Centering all. Even if the image width is greater than the container, showing the entire image. I can only do this using JS.

I know it's not the purpose of the post, but it was my purpose when I came here, and it may be useful to someone!

<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style type="text/css">

        body {
            margin: 0;
            overflow: hidden;
            width: 100vw;
            height: 100vh;
            background-color: #000;
        }

        #container{
            position: absolute;
            top: 0px;
            width: 100vw;
            height: 100vh;
            text-align: center;
        }

        #my_img{
            height: 100%;
            width: auto;
        }

    </style>

</head>
<body>
    <div id="container">
        <img src="images/filename.jpg" id="my_img">
    </div>

    <script type="text/javascript">
        
        window.onload = function () {
            imgElem = document.getElementById('my_img');
            if (imgElem.width > document.body.scrollWidth) {
                // image is larger than container >> adjust by width and center
                imgElem.style.height = 'auto';
                imgElem.style.width = '100%';
                imgElem.style.position = 'relative';
                imgElem.style.transform = 'translateY(-50%)';
                imgElem.style.top = '50%';
            }
        }
        
    </script>

</body>
</html>
Norford answered 10/11, 2022 at 13:20 Comment(0)
A
-3

Just fix the height of the image & provide width = auto

img{
    height: 95vh;
    width: auto;
}
Actinochemistry answered 21/7, 2019 at 12:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.