185

I have a 48x48 div and inside it there is an img element, I want to fit it into the div without losing any part, in the mean time the ratio is kept, is it achievable using html and css?

Matthew Simoneau
  • 6,199
  • 6
  • 35
  • 46
Bin Chen
  • 61,507
  • 53
  • 142
  • 183

14 Answers14

346

Use max-height:100%; max-width:100%; for the image inside the div.

Michael
  • 4,188
  • 2
  • 14
  • 6
  • I agree. What if you want non-JavaScript-enabled browsers to be able to display it? I am always a fan of pure HTML+CSS solutions to web design problems. – DankMemes Dec 08 '12 at 01:27
  • 4
    @ZoveGames Non-JS enabled browsers? Yahoo stats from 2010 show a 1.3% average. I think it's safe to assumed that a. it's probably lower today and b. http://programmers.stackexchange.com/questions/26179/why-do-people-disable-javascript/26186#26186 – EasyCo Jan 11 '13 at 04:26
  • that is a good answer, but am I able to get the adapted image dimension in pixel? What would be the js method to get this, without css tricks? – albanx Jul 02 '13 at 10:45
  • 5
    It does not work for me... It makes the image 100% of it's own size (eg.: 300px wide for an image that actually is 300px wide). – Tomáš Zato Sep 28 '13 at 13:27
  • 1
    There is some awful Chrome-on-Windows specific bug that this causes. Potentially some bad interaction with certain smoothscroll plugins I have. It ends up trying to scroll the body even though the mouse is over a `overflow:scroll` div with a large image in it. Curious. Even more strange: Max's solution actually fixes it. I'm quite fed up with CSS, really. Used to be powerful and cool. Now implementations just produce buggy inconsistency after buggy inconsistency. – Steven Lu Jan 30 '14 at 08:36
  • 29
    only works when scaling down an image. if you want to fit a small image in a bigger container, this won't work – Yossi Shasho Jun 24 '14 at 07:56
  • It doesn't work for me either. Applying these rules do not affect my image whatsoever. Image is bigger than div. – Caio Mar Jul 01 '15 at 02:26
  • 3
    It doesn't preserve the original aspect ratio of the image. – Ĭsααc tիε βöss Dec 07 '15 at 07:10
  • 1
    I don't believe this solution works if the containing div does not have an absolute size. – Overdrivr Dec 21 '15 at 11:26
  • It works for me with prozentual width and fixed height (correct scaling down, aspect ratio is perfect). If I insert a flex-grow div next to it, I additionally can align it correctly. Thanks! Scaling up does not work, but I am glad that at least this works. – JFFIGK Jan 07 '20 at 02:15
  • @Andrii Verbytskyi answer and comments provide everything: scaling up and positioning – JFFIGK Jan 07 '20 at 02:26
132

CSS Object-fit

Unfortunately max-width + max-height do not fully cover my task... So I have found another solution:

To save the Image ratio while scaling you also can use object-fit CSS3 propperty.

Useful article: Control image aspect ratios with CSS3

img {
    width: 100%; /* or any custom size */
    height: 100%; 
    object-fit: contain;
}

Bad news: IE not supported (Can I Use)

Andrii Verbytskyi
  • 7,155
  • 3
  • 47
  • 38
  • 9
    This must be marked as the answer.. "object-fit" worked perfectly. – Ĭsααc tիε βöss Dec 07 '15 at 07:15
  • Oddly, it looks like support for this was introduced in iOS 8.1, not 8.0. – ray Jun 23 '16 at 13:15
  • 6
    `object-fit: cover;` worked for me. Here: http://stackoverflow.com/questions/9071830/contain-an-image-within-a-div – Deke Jul 27 '16 at 01:46
  • 2
    If you want the image to be in the top left rather than centered, you also need to use object-position 0 0. – Chris Rae Oct 03 '16 at 22:36
  • This is the only answer that worked for me to create a responsive image background that filled the screen while maintaining the image aspect ratio. – Ray Li Jul 17 '17 at 02:38
  • Edge is now supported `object-fit: cover` and for IE use `@supports` which tell the browser if the particular property not supported then use this. MDN link - [MDN link](https://developer.mozilla.org/en-US/docs/Web/CSS/@supports) – Pranab Apr 15 '19 at 10:01
  • Object-position: https://developer.mozilla.org/de/docs/Web/CSS/object-position (also works in edge) – JFFIGK Jan 07 '20 at 02:25
83

You will need some JavaScript to prevent cropping if you don't know the dimension of the image at the time you're writing the css.

HTML & JavaScript

<div id="container">
    <img src="something.jpg" alt="" />
</div>

<script type="text/javascript">
(function() {

var img = document.getElementById('container').firstChild;
img.onload = function() {
    if(img.height > img.width) {
        img.height = '100%';
        img.width = 'auto';
    }
};

}());
</script>

CSS

#container {
   width: 48px;
   height: 48px;
}

#container img {
   width: 100%;
}

If you use a JavaScript Library you might want to take advantage of it.

Thomas
  • 3,004
  • 23
  • 17
  • 2
    Michael's answer is much simpler and it doesn't use Javascript. I don't know about browser compatibility though. – weberc2 Jun 03 '12 at 21:13
  • 3
    No, Michael's answer works as long as the image is bigger than the div. If you want the image to fill the div regarding of image size (and, if you don't know the image size in advance, you do), this is the way to go. – Rémy DAVID Jul 25 '12 at 13:02
  • 2
    Could you not use max-height:100%; max-width:100%; min-width:100%; min-height:100% and get the same result then? Honest question. – Daniel Casserly Aug 08 '12 at 13:28
  • No, by doing that you force the width and height to be be 100%, so you change the image aspect ratio. – gztomas Aug 01 '13 at 19:51
  • onload won't be called when the image is cached in the browser, so this will only work when the image is loaded for the first time. – Redtopia Apr 27 '14 at 01:24
  • http://stackoverflow.com/questions/3877027/jquery-callback-on-image-load-even-when-the-image-is-cached in case if image loaded from cache – KregHEk Apr 29 '14 at 09:54
  • Please, be aware that img.height > img.width is only a valid test if the height of the container equals the width of the container. (as, indeed,the OP asks). In other cases you would need to compare the aspect ratio of the image with the aspect ration of the container. – Ideogram Sep 01 '14 at 13:47
45

Using CSS only:

div > img {
  width: auto;
  height : auto;
  max-height: 100%;
  max-width: 100%;
}
Max
  • 1,090
  • 10
  • 23
19

HTML

<div>
    <img src="something.jpg" alt="" />
</div>

CSS

div {
   width: 48px;
   height: 48px;
}

div img {
   display: block;
   width: 100%;
}

This will make the image expand to fill its parent, of which its size is set in the div CSS.

alex
  • 479,566
  • 201
  • 878
  • 984
9

I was having a lot of problems to get this working, every single solution I found didn't seem to work.

I realized that I had to set the div display to flex, so basically this is my CSS:

div{
display: flex;
}

div img{ 
max-height: 100%;
max-width: 100%;
}
Bartho Bernsmann
  • 2,393
  • 1
  • 25
  • 34
  • My images are distorted with this solution in Chrome Version 61 – Yevgeniy Afanasyev Nov 12 '17 at 01:29
  • Maybe your div has a max-height/height or width set, and that is causing your image distortion. – Bartho Bernsmann Nov 14 '17 at 05:40
  • Exactly my point.. The image is distorted because you are setting the width and height on your
    – Bartho Bernsmann Nov 14 '17 at 13:34
  • For your example.. I believe you are looking for something like on your image CSS: height: auto; width: 100%; – Bartho Bernsmann Nov 14 '17 at 13:35
  • the task was to fit image into a div, it implies that div has the dimensions and the image has only aspect ratio. I need to set height to some value, otherwise the question conditions will be distorted as well as my image. Please have a look at [JS fiddle](https://jsfiddle.net/jej138pe/) and change what you think is needed to make it work. Thanks. – Yevgeniy Afanasyev Nov 14 '17 at 22:10
8

Try CSS:

img {
  object-fit: cover;
  height: 48px;
}
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Faisal
  • 1,907
  • 1
  • 22
  • 29
7

For me, the following CSS worked (tested in Chrome, Firefox and Safari).

There are multiple things working together:

  • max-height: 100%;, max-width: 100%; and height: auto;, width: auto; make the img scale to whichever dimension first reaches 100% while keeping the aspect ratio
  • position: relative; in the container and position: absolute; in the child together with top: 50%; and left: 50%; center the top left corner of the img in the container
  • transform: translate(-50%, -50%); moves the img back to the left and top by half its size, thus centering the img in the container

CSS:

.container {
    height: 48px;
    width: 48px;

    position: relative;
}

.container > img {
    max-height: 100%;
    max-width: 100%;
    height: auto;
    width: auto;

    position: absolute;
    top: 50%;
    left: 50%;

    transform: translate(-50%, -50%);
}
VSchlattinger
  • 71
  • 1
  • 2
3

Super late but, try this solution:

.parent {
  display: flex;
  min-height: 400px; /* if you prefer */
}

.parent > img {
  display: block;
  width: 100%;
  max-width: 100%;
  object-fit: cover;
}
  
Pratikno Rulianto
  • 1,049
  • 7
  • 8
2

Setting the photo as a background image will give us more control over size and placement, leaving the img tag to serve a different purpose...

Below, if we want the div to be the same aspect ratio as the photo, then placeholder.png is a small transparent image with the same aspect ratio as photo.jpg. If the photo is a square, it's a 1px x 1px placeholder, if the photo is a video thumbnail, it's a 16x9 placeholder, etc.

Specific to the question, use a 1x1 placeholder to maintain the div's square ratio, with a background image using background-size to maintain the photo's aspect ratio.

I used background-position: center center; so the photo will be centered in the div. (Aligning the photo in the vertical center or bottom would get ugly with the photo in the img tag.)

div {
    background: url(photo.jpg) center center no-repeat;
    background-size: contain;
    width: 48px; // or a % in responsive layout
}
img {
    width: 100%;
}

<div><img src="placeholder.png"/></div>

To avoid an extra http request, convert the placeholder image to a data: URL.

<img src="data:image/png;base64,..."/>
Webveloper
  • 1,059
  • 10
  • 15
1

you can use class "img-fluid" for newer version i.e Bootstrap v4.

and can use class "img-responsive" for older version like Bootstrap v3.

Usage:-

img tag with :-

class="img-fluid"

src="..."

1

What worked for me was:

<div style='display: inline-flex; width: 80px; height: 80px;'>
<img style='max-width: 100%; max-height: 100%' src='image file'>
</div>

inline-flex was required to keep the images from going outside of the div.

Nomad77
  • 105
  • 3
0

Here's an all JavaScript approach. It scales an image incrementally down until it fits correctly. You choose how much to shrink it each time it fails. This example shrinks it 10% each time it fails:

let fit = function (el, w, h, percentage, step)
{
    let newH = h;
    let newW = w;

    // fail safe
    if (percentage < 0 || step < 0) return { h: h, w: w };
    if (h > w)
    {
        newH = el.height() * percentage;
        newW = (w / h) * newH;
        if (newW > el.width())
        {
            return fit(el, w, h, percentage - step, step);
        }
    }
    else
    {
        newW = el.width() * percentage;
        newH = (h / w) * newW;
        if (newH > el.height())
        {
            return fit(el, w, h, percentage - step, step);
        }
    }

    return { h: newH, w: newW };
};

img.bind('load', function ()
{
    let h = img.height();
    let w = img.width();
    let newFit = fit($('<img-wrapper-selector>'), w, h, 1, 0.1);

    img.width(newFit.w);
    img.height(newFit.h);
});

Feel free to copy and paste directly.

Jared Beach
  • 2,635
  • 34
  • 38
0

I ran into the same problem. My solution is to put a "display block" on the image tag to avoid the small overflow at the bottom of the div container.

You can see an example

.page {
  background-color: lightgreen;
  height: 100vh;
}
  
.image-container {
  background-color: lightcoral;
}
    
img {
  width: 100%;
  display: block;
}
<div class="page">
  <div class="image-container">
    <img src="https://www.sprayedout.com/wp-content/uploads/2020/11/countryside-nature-landscape-sunset-web.jpg" alt="" />
  </div>
</div>
Guillaume
  • 111
  • 1
  • 5