126

If I have:

#logo {
    width: 400px;
    height: 200px;
}

then

<img id="logo" src="logo.jpg"/>

will stretch to fill that space. I want the image to stay the same size, but for it to take up that much space in the DOM. Do I have to add an encapsulating <div> or <span>? I hate adding markup for styling.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Paul Tarjan
  • 48,968
  • 59
  • 172
  • 213

13 Answers13

132

Yes you need an encapsulating div:

<div id="logo"><img src="logo.jpg"></div>

with something like:

#logo { height: 100px; width: 200px; overflow: hidden; }

Other solutions (padding, margin) are more tedious (in that you need to calculate the right value based on the image's dimensions) but also don't effectively allow the container to be smaller than the image.

Also, the above can be adapted much more easily for different layouts. For example, if you want the image at the bottom right:

#logo { position: relative; height: 100px; width: 200px; }
#logo img { position: absolute; right: 0; bottom: 0; }
KyleMit
  • 30,350
  • 66
  • 462
  • 664
cletus
  • 616,129
  • 168
  • 910
  • 942
  • 7
    You can replace the
    tag with
    : adds semantic and you can give a caption (
    ) for it, if necessary. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure
    – Mateus Leon Jun 01 '15 at 03:30
  • Also, if it is for branding use, on the website presentation, use

    (if index) or

    (if other), applying the title and alt attributes to the , so you can add SEO friendly markup. They are block level elements too, like div, and can be wrappers for your crop functionality.

    – Mateus Leon Jun 01 '15 at 03:37
116

2017 answer

CSS object fit works in all current browsers. It allows the img element to be larger without stretching the image.

You can add object-fit: cover; to your CSS.

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
Dante
  • 1,161
  • 1
  • 7
  • 2
30

Load the image as a background for a div.

Instead of:

<img id='logo' src='picture.jpg'>

do

<div id='logo' style='background:url(picture.jpg)'></div>

All browsers will crop the part of the image that doesn't fit.
This has several advantages over wrapping it an element whose overflow is hidden:

  1. No extra markup. The div simply replaces the img.
  2. Easily center or set the image to another offset. eg. url(pic) center top;
  3. Repeat the image when small enough. (Ok, I don't know, why you would want that)
  4. Set a bg color in the same statement, easily apply the same image to multiple elements, and everything that applies to bg images.

Update: This answer is from before object-fit; you should now probably use object-fit/object-position.

It is still useful for older browsers, for extra properties (such as background-repeat), and for edge cases (For example, workaround Chrome bugs with flexbox and object-position and FF's (former?) issues with grid + autoheight + object-fit. Wrapper divs in grid / flexbox often give... unintuitive results.)

peterh
  • 11,875
  • 18
  • 85
  • 108
SamGoody
  • 13,758
  • 9
  • 81
  • 91
  • 4
    Those who gave a -1 should please explain for the benefit of other users. Personally, have done this with excellent results, even on IE6 and Safari on iOS. – SamGoody Aug 31 '12 at 08:41
  • 1
    Just wanted to add - this is generally a good approach. People even specify background position coordinates for image sprite sheets as optimization. One difference, however, is that it doesn't have the error event handler that has – badunk Mar 22 '13 at 18:42
  • I also added a class to the div with these contents: `background-repeat:no-repeat !important; float:left; width:100px; height:100px; ` – Nils Nov 27 '13 at 23:12
  • 3
    Some browsers by default will not print background images, so this might not be a good approach if you want to let users print that page. – Bennett McElwee Mar 08 '15 at 20:22
  • 5
    This is not semantically correct. If this is useful, why the HTML5 is placing more image related tags, to optimize the semantic, with figcaption, picture? Use the img tag as it was designed for and stop replacing everything with
    s.
    – Mateus Leon Jun 01 '15 at 03:28
  • @MateusLeon is correct. Using this one will not result to a better SEO. – Jonas Jan 02 '20 at 10:08
  • @Jonas Estillore - Who said anything about SEO? The advantages are maintainability, browser support, feature set, etc. See my update. – SamGoody Jan 02 '20 at 11:12
26

CSS3 object-fit

Am not sure how far its been implemented by webkit, IE and firefox. But Opera works like magic

object-fit works with SVG content, but the same effect can also be achieved by setting the preserveAspectRatio="" attribute in the SVG itself.

img {
  height: 100px;
  width: 100px;
  -o-object-fit: contain;
}

Chris Mills demo's it here http://dev.opera.com/articles/view/css3-object-fit-object-position/

theCrab
  • 556
  • 5
  • 8
  • 2
    1+ This is really cool. Too bad there is [limited support..](http://caniuse.com/object-fit) It looks like Chrome 32 is the first to support it without vendor prefixes. – Josh Crozier Feb 15 '14 at 22:20
  • This is fantastic, works like a charm. Just adding a single property fixed it all. I just needed for Chrome and it works. And yes, without vendor prefix. Thanks. – whyAto8 Dec 16 '14 at 08:40
15
#logo {
    width: 400px;
    height: 200px;

    /*Scale down will take the necessary specified space that is 400px x 200px without stretching the image*/
    object-fit:scale-down;
}
Manoj Selvin
  • 2,247
  • 24
  • 20
9

Make a div and give it a class. Then drop a img in it.

<div class="mydiv">

<img src="location/of/your/image" ></img>

</div>

Set the size of your div and make it relative.

    .mydiv {
        position: relative;
        height:300px;
        width: 100%;
        overflow: hidden;
    }

then style your image

img {
    width: 100%;
    height: auto;
    overflow: hidden;
}

Hope that helps

Leandro Bardelli
  • 10,561
  • 15
  • 79
  • 116
Sabba Keynejad
  • 7,895
  • 2
  • 26
  • 22
7
<img style="object-fit: contain" src="...">

Worked perfectly for me.

Savlon
  • 744
  • 2
  • 11
  • 18
  • 1
    This is what I ended up using. The "object-fit: cover" ruined the images somehow, but "contain" did exactly what I needed it to. It caused all images to display without stretch, distortion, etc. regardless if they were portrait, landscape etc. – CaptainGenesisX Sep 29 '22 at 13:18
3

You can use as below :

.width100 {
  max-width: 100px;
  height: 100px;
  width: auto;
  border: solid red;
}
<img src="https://www.gravatar.com/avatar/dc48e9b92e4210d7a3131b3ef46eb8b1?s=512&d=identicon&r=PG" class="width100" />
PurTahan
  • 789
  • 8
  • 24
1

Do I have to add an encapsulating <div> or <span>?

I think you do. The only thing that comes to mind is padding, but for that you would have to know the image's dimensions beforehand.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
0

you can try setting the padding instead of the height/width.

Bless Yahu
  • 1,331
  • 1
  • 12
  • 25
0

What I can think of is to stretch either width or height and let it resize in ratio-aspect. There will be some white space on the sides. Something like how a Wide screen displays a resolution of 1024x768.

mauris
  • 42,982
  • 15
  • 99
  • 131
0

If using flexbox is a valid option for you (don't need to suport old browsers), check my other answer here (which is possibly a duplicate of this one):

Basically you'd need to wrap your img tag in a div and your css would look like this:

.img__container {
    display: flex;
    padding: 15px 12px;
    box-sizing: border-box;
    width: 400px; height: 200px;

    img {
        margin: auto;
        max-width: 100%;
        max-height: 100%;
    }
}
Community
  • 1
  • 1
rafaelbiten
  • 6,074
  • 2
  • 31
  • 36
-1

This is quite old question, but I have had the exact same annoying issue where everything worked fine for Chrome/Edge (with object-fit property) but same css property did not work in IE11 (since its unsupported in IE11), I ended up using HTML5 "figure" element which solved all my problems.

I personally did not use the outer DIV tag since that did not help at all in my case, so I avoided the outer DIV and simply replaced with 'figure' element.

The below code forces the image to reduce/scale down nicely (without changing the original aspect ratio).

<figure class="figure-class">
  <img class="image-class" src="{{photoURL}}" />
</figure>

and css classes:

.image-class {
    border: 6px solid #E8E8E8;
    max-width: 189px;
    max-height: 189px;
}

.figure-class {
    width: 189px;
    height: 189px;
}
nakul2013
  • 17
  • 2