508

I have an image, and I want to set it a specific width and height (in pixels)

But If I set width and height using css (width:150px; height:100px), image will be stretched, and It may be ugly.

How to Fill images to a specific size using CSS, and not stretching it?

Example of fill and stretching image:

Original Image:

Original

Stretched Image:

Stretched

Filled Image:

Filled

Please note that in the Filled image example above: first, image is resized to 150x255 (maintained aspect ratio), and then, it cropped to 150x100.

Mahdi Ghiasi
  • 13,903
  • 17
  • 65
  • 118

18 Answers18

746

You can use the css property object-fit. ("sets how the content of a replaced element, such as an <img> or <video>, should be resized to fit its container.")

.cover {
  object-fit: cover;
  width: 50px;
  height: 100px;
}
<img src="http://i.stack.imgur.com/2OrtT.jpg" class="cover" width="242" height="363" />

See example here

There's a polyfill for IE: https://github.com/anselmh/object-fit

Related: object-position (specifies the alignment of an element's contents within its box.)

afonsoduarte
  • 10,488
  • 2
  • 15
  • 10
  • 14
    Interesting to see that this can be done with `img` tags too (not only `background-image` method as described in the answer above). Thank you :) – Mahdi Ghiasi Jun 02 '15 at 12:38
  • 3
    Unfortunately `background-size` is rarely a viable solution in my projects. You're less likely to receive any SEO benefit and cannot provide an ALT tag, caption, etc to accompany the image where you may want to provide additional context for screen readers. – Markus Dec 11 '15 at 17:42
  • 3
    This is cool, but there is no IE support. None of the polyfills work anymore. – Jake Sep 07 '16 at 02:00
  • 4
    Just using `object-fit: cover;` does it. Thanks a lot – Luka Mar 06 '17 at 20:30
  • 1
    Best solution ever! – Aarón Castro Apr 21 '17 at 17:22
  • 3
    now 2017 browser which support it should increased. When the image is bigger `scale-down' give better option. [scale-down](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit?v=example) – Adi Prasetyo May 31 '17 at 07:31
  • It should be noted that both a **width and height must be declared** for the image (percentages are accepted) in order for this to work. I spent a long time trying to figure out why this wouldn't work for me - I hadn't set a height on the image. – Luke Jul 26 '17 at 11:10
  • 1
    I used `width: 100%; min-height: 100%; object-fit: cover;` and it worked pretty well. – kiko carisse Aug 18 '17 at 19:49
  • Its very important - `object-fit: cover` should be accompanied by `width` and `height`, `min-width` did not work for me – Jacek Dziurdzikowski Feb 16 '18 at 12:41
  • 2
    Thankfully, it is 2018 and this is supported on most browsers now. I didn't even have to specify the width and height attributes for it to work. – pulsejet Mar 30 '18 at 09:32
  • I like to use this: margin: 0 auto; max-height: 100%; max-width: 100%; object-fit: cover; – Kody Aug 31 '18 at 17:22
  • 2
    "No IE support" is a laughable reason to throw out an otherwise elegant solution. IE makes up less than 3% of the market at this point. There is no reason not to upgrade when both Chrome and Firefox are completely 100% free. – Jess May 17 '19 at 18:45
  • This is the proper answer, the image does not get stretched and remains centered. Thanks for this. – SJacks Dec 26 '19 at 08:00
  • This is the correct answer. Just created a new account just to upvote and comment this. – Christopher Healey Oct 01 '20 at 10:57
  • As `object-fit` is supported in pretty much every modern browser these days, I'm selecting this answer as the accepted answer. – Mahdi Ghiasi Oct 10 '20 at 21:00
  • yep, this is the solution if the class is directly in the img property! – Alexander Feb 19 '21 at 11:46
428

If you want to use the image as a CSS background, there is an elegant solution. Simply use cover or contain in the background-size CSS3 property.

.container {
  width: 150px;
  height: 100px;
  background-image: url("http://i.stack.imgur.com/2OrtT.jpg");
  background-size: cover;
  background-repeat: no-repeat;
  background-position: 50% 50%;
}
<div class="container"></div>​

While cover will give you a scaled up image, contain will give you a scaled down image. Both will preserve the pixel aspect ratio.

http://jsfiddle.net/uTHqs/ (using cover)

http://jsfiddle.net/HZ2FT/ (using contain)

This approach has the advantage of being friendly to Retina displays as per Thomas Fuchs' quick guide.

It's worth mentioning that browser support for both attributes excludes IE6-8.

johannchopin
  • 11,813
  • 8
  • 41
  • 91
Marcelo De Polli
  • 26,713
  • 4
  • 38
  • 47
  • Thank you, but can you explain more about the advantage of this method on Retina displays? – Mahdi Ghiasi Aug 01 '12 at 16:50
  • 1
    Since you can resize the image purely in the CSS, this allows you to use a large image and then scale it down according to each device's pixel density by using media queries. – Marcelo De Polli Aug 01 '12 at 16:59
  • Anyway, I like a pure CSS way more than a jQuery way! Thanks! – Mahdi Ghiasi Aug 01 '12 at 22:22
  • 1
    Could you explain why in this case the background-position seems to indicate the position of the center of the image rather than it's top-left corner? Is it a consequence of background-size: cover? – matteo Mar 01 '14 at 18:47
  • 1
    mine just covers the entire DIV expanding the image. I don't see the curve ending. – SearchForKnowledge Oct 15 '14 at 15:26
  • 3
    What is `background-repeat: no-repeat;` for? If the image covers it's container, it won't repeat itself anyway. – lurkit Jul 15 '16 at 03:23
  • @depa if this image is not in background then how to fix this. can you please answer me – Amaresh Tiwari Aug 05 '16 at 13:42
  • 4
    'background-position' could be set to 'center center' too. eg.: .container { ... background-position: center center; } – Leo Ribeiro Feb 21 '17 at 14:56
  • 1
    CSS tricks disagrees with you about preserving the pixel aspect ratio: [Cover tells the browser to make sure the image always covers the entire container, even if it has to stretch the image](https://css-tricks.com/almanac/properties/b/background-size/) (But I'm not sure if they are right) – Felix Eve Mar 29 '17 at 05:41
  • My god did this just help me – Hews Feb 08 '19 at 18:20
85

Enhancement on the accepted answer by @afonsoduarte.
in case you are using bootstrap


There are three differences:
  1. Providing width:100% on the style.
    This is helpful if you are using bootstrap and want the image to stretch all the available width.

  2. Specifying the height property is optional, You can remove/keep it as you need

    .cover {
       object-fit: cover;
       width: 100%;
       /*height: 300px;  optional, you can remove it, but in my case it was good */
    }
    
  3. By the way, there is NO need to provide the height and width attributes on the image element because they will be overridden by the style.
    so it is enough to write something like this.

    <img class="cover" src="url to img ..."  />
    
Hakan Fıstık
  • 14,367
  • 10
  • 94
  • 117
57

The only real way is to have a container around your image and use overflow:hidden:

HTML

<div class="container"><img src="ckk.jpg" /></div>

CSS

.container {
    width: 300px;
    height: 200px;
    display: block;
    position: relative;
    overflow: hidden;
}

.container img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
}

It's a pain in CSS to do what you want and center the image, there is a quick fix in jquery such as:

var conHeight = $(".container").height();
var imgHeight = $(".container img").height();
var gap = (imgHeight - conHeight) / 2;
$(".container img").css("margin-top", -gap);

http://jsfiddle.net/x86Q7/2/

Hakan Fıstık
  • 14,367
  • 10
  • 94
  • 117
Dominic Green
  • 10,024
  • 4
  • 28
  • 34
  • 1
    Thanks. it worked, but it crops the image from **top**. (see this: http://jsfiddle.net/x86Q7/ ) Isn't there any way to crop image from **center**? – Mahdi Ghiasi Aug 01 '12 at 10:50
  • 1
    @MahdiGhiasi: Change top and left properties in .container img css!! – Ali Ben Messaoud Aug 01 '12 at 10:53
  • I may set `margin-top` of image by for example `50px` (see this: http://jsfiddle.net/x86Q7/1/ ), but How to crop it from real **center**? (Without jQuery?) – Mahdi Ghiasi Aug 01 '12 at 10:56
  • 2
    Ahh sorry didnt see your comment but i added the jquery just incase :) – Dominic Green Aug 01 '12 at 10:58
  • Not sore what you're using it for, but there are some nice php libraries that can do this for you, that way you can save the thumbnail and load it up whenever you need it. – woutr_be Aug 01 '12 at 11:08
  • 1
    Great solution! For me the vertical fill was more important than the horizontal, so I just had to change "width: 100%" to "height: 100%" for the '.container img' class. Thank you! – deebs Dec 18 '14 at 15:11
  • What I was looking for. Thanks! – Hristo Enev Jul 10 '15 at 06:28
  • This works fine if your container is a fixed size, otherwise you can hit "coverage" issues based on the width of the container element and the image's aspect ratio. So for responsive design (when widths may stretch/shrink at different media widths) I use background cover which guarantees the area is covered. – mhapps Jun 26 '18 at 09:45
  • what is the image is higher than wider, does not work – DavidDunham Dec 10 '21 at 09:25
29

CSS solution no JS and no background image:

Method 1 "margin auto" ( IE8+ - NOT FF!):

div{
  width:150px; 
  height:100px; 
  position:relative;
  overflow:hidden;
}
div img{
  position:absolute; 
  top:0; 
  bottom:0; 
  margin: auto;
  width:100%;
}
<p>Original:</p>
<img src="http://i.stack.imgur.com/2OrtT.jpg" alt="image"/>

<p>Wrapped:</p>
<div>
  <img src="http://i.stack.imgur.com/2OrtT.jpg" alt="image"/>
</div>

http://jsfiddle.net/5xjr05dt/

Method 2 "transform" ( IE9+ ):

div{
  width:150px; 
  height:100px; 
  position:relative;
  overflow:hidden;
}

div img{
  position:absolute; 
  width:100%;
  top: 50%;
  -ms-transform: translateY(-50%);
  -webkit-transform: translateY(-50%);
  transform: translateY(-50%);
}
<p>Original:</p>
<img src="http://i.stack.imgur.com/2OrtT.jpg" alt="image"/>

<p>Wrapped:</p>
<div>
  <img src="http://i.stack.imgur.com/2OrtT.jpg" alt="image"/>
</div>

http://jsfiddle.net/5xjr05dt/1/

Method 2 can be used to center an image in a fixed width / height container. Both can overflow - and if the image is smaller than the container it will still be centered.

http://jsfiddle.net/5xjr05dt/3/

Method 3 "double wrapper" ( IE8+ - NOT FF! ):

.outer{
  width:150px; 
  height:100px; 
  margin: 200px auto; /* just for example */
  border: 1px solid red; /* just for example */
  /* overflow: hidden; */ /* TURN THIS ON */
  position: relative;
}
.inner { 
    border: 1px solid green; /* just for example */
    position: absolute;
    top: 0;
    bottom: 0;
    margin: auto;
    display: table;
    left: 50%;
}
.inner img {
    display: block;
    border: 1px solid blue; /* just for example */
    position: relative;
    right: 50%;
    opacity: .5; /* just for example */
}
<div class="outer">
  <div class="inner">
     <img src="http://i.stack.imgur.com/2OrtT.jpg" alt="image"/>
  </div>
</div>

http://jsfiddle.net/5xjr05dt/5/

Method 4 "double wrapper AND double image" ( IE8+ ):

.outer{
  width:150px; 
  height:100px; 
  margin: 200px auto; /* just for example */
  border: 1px solid red; /* just for example */
  /* overflow: hidden; */ /* TURN THIS ON */
  position: relative;
}
.inner { 
    border: 1px solid green; /* just for example */
    position: absolute;
    top: 50%;
    bottom: 0;
    display: table;
    left: 50%;
}
.inner .real_image {
    display: block;
    border: 1px solid blue; /* just for example */
    position: absolute;
    bottom: 50%;
    right: 50%;
    opacity: .5; /* just for example */
}

.inner .placeholder_image{
  opacity: 0.1; /* should be 0 */
}
<div class="outer">
  <div class="inner">
    <img class="real_image" src="http://i.stack.imgur.com/2OrtT.jpg" alt="image"/>
    <img class="placeholder_image"  src="http://i.stack.imgur.com/2OrtT.jpg" alt="image"/>
  </div>
</div>

http://jsfiddle.net/5xjr05dt/26/

  • Method 1 has slightly better support - you have to set the width OR height of image!
  • With the prefixes method 2 also has decent support ( from ie9 up ) - Method 2 has no support on Opera mini!
  • Method 3 uses two wrappers - can overflow width AND height.
  • Method 4 uses a double image ( one as placeholder ) this gives some extra bandwidth overhead, but even better crossbrowser support.

Method 1 and 3 don't seem to work with Firefox

Hakan Fıstık
  • 14,367
  • 10
  • 94
  • 117
J.T. Houtenbos
  • 936
  • 7
  • 15
  • This is the only one that actually works (minus js solutions). Thanks! – Jake Sep 07 '16 at 01:59
  • It is limited to overflowing either height or width, but an interesting solution. – Jake Sep 07 '16 at 02:21
  • 1
    @Jake - It is possible to overflow width AND height with method 2 above - see my updated answer with the extra fiddle. – J.T. Houtenbos Sep 07 '16 at 12:23
  • Yeah. It is definitely a great answer. I will fool around with it some more. It was a little quirky for an image wider than taller that needed to be responsive, but there are lots of applications for this. – Jake Sep 07 '16 at 15:44
  • 1
    @Jake - Cool - I found a 3th method to do horizontal centering. I extended this method to also support vertical centering. I will post my addition as a 3th method above. It seems it is IE7+ proof ( even lower possibly ). Here is the original answer: http://stackoverflow.com/questions/3300660/how-do-i-center-an-image-if-its-wider-than-its-container/3302072#3302072 – J.T. Houtenbos Sep 07 '16 at 17:55
  • @Jake - got the 3th method figured out and inserted it in the post above – J.T. Houtenbos Sep 07 '16 at 20:00
12

Solution not requiring image as a background and will auto-resize without being cut-off or distorting.

Another solution is to put the image in a container with the desired width and height. Using this method you would not have to set the image as a background image of an element.

Then you can do this with an img tag and just set a max-width and max-height on the element.

CSS:

.imgContainer {
    display: block;
    width: 150px; 
    height: 100px;
}

.imgContainer img {
    max-width: 100%;
    max-height: 100%;
}

HTML:

<div class='imgContainer'>
    <img src='imagesrc.jpg' />
</div>

Now when you change the size of the container the image will automatically grow as large as it can without going outside the bounds or distorting.

If you want to center the image vertically and horizontally you can change the container css to:

.imgContainer {
    display: table-cell;
    width: 150px; 
    height: 100px;
    text-align: center;
    vertical-align: middle;
}

Here is a JS Fiddle http://jsfiddle.net/9kUYC/2/

earl3s
  • 2,283
  • 1
  • 22
  • 24
  • It's not the same as cover in CSS, where one of the resulting dimensions is always beyond 100% (or equal in edge case) – Miroshko Dec 07 '14 at 16:19
  • No, this solution makes sure that it's never stretched beyond 100%, which is what part of the question was about. They didn't want to have the image distort or grow beyond the original dimensions. – earl3s Dec 08 '14 at 18:52
  • 3
    The question was "How to Fill" with an example of filled image, which is obviously cropped. – Miroshko Dec 10 '14 at 15:52
  • But what if you need the image to be responsive? Defining a specific width and height isn't going to work – Ricardo Zea Aug 30 '17 at 05:03
  • Ricardo, that's true. I don't believe his question was about a responsive image size though. Just about an image filling a container properly. – earl3s Aug 31 '17 at 06:48
  • 2
    It was what I needed. Thanks! – Nico Rodsevich Mar 30 '19 at 15:28
  • @RicardoZea if you set the .imgContainer to be a responsive div the whole image becomes responsive too. – earl3s Apr 21 '21 at 19:21
  • @earl3s, as I read my comment from almost four years ago, lol, I realize that I probably didn't ask the question right. The image is actually already responsive, what is not responsive is its parent container, hence, your clarification :) – Ricardo Zea Apr 22 '21 at 03:19
7
  • Not using css background
  • Only 1 div to clip it
  • Resized to minimum width than keep correct aspect ratio
  • Crop from center (vertically and horizontally, you can adjust that with the top, lef & transform)

Be careful if you're using a theme or something, they'll often declare img max-width at 100%. You got to make none. Test it out :)

https://jsfiddle.net/o63u8sh4/

<p>Original:</p>
<img src="http://i.stack.imgur.com/2OrtT.jpg" alt="image"/>

<p>Wrapped:</p>
<div>
    <img src="http://i.stack.imgur.com/2OrtT.jpg" alt="image"/>
</div>


div{
  width:150px; 
  height:100px; 
  position:relative;
  overflow:hidden;
}
div img{
  min-width:100%;
  min-height:100%;
  height:auto;
  position:relative;
  top:50%;
  left:50%;
  transform:translateY(-50%) translateX(-50%);
}
dmegatool
  • 173
  • 1
  • 7
5

Building off of @Dominic Green's answer using jQuery, here is a solution that should work for images that are either wider than they are high or higher than they are wide.

http://jsfiddle.net/grZLR/4/

There is probably a more elegant way of doing the JavaScript, but this does work.

function myTest() {
  var imgH = $("#my-img").height();
  var imgW = $("#my-img").width();
  if(imgW > imgH) {
    $(".container img").css("height", "100%");
    var conWidth = $(".container").width();
    var imgWidth = $(".container img").width();
    var gap = (imgWidth - conWidth)/2;
    $(".container img").css("margin-left", -gap);
  } else {
    $(".container img").css("width", "100%");
    var conHeight = $(".container").height();
    var imgHeight = $(".container img").height();
    var gap = (imgHeight - conHeight)/2;
    $(".container img").css("margin-top", -gap);
  }
}
myTest();
ramdog
  • 476
  • 5
  • 8
4

I helped build a jQuery plugin called Fillmore, which handles the background-size: cover in browsers that support it, and has a shim for those that don't. Give it a look!

Aidan Feldman
  • 4,793
  • 35
  • 46
4

This will Fill images to a specific size, without stretching it or without cropping it

img{
    width:150px;  //your requirement size
    height:100px; //your requirement size

/*Scale down will take the necessary specified space that is 150px x 100px without stretching the image*/
    object-fit:scale-down;
}
Manoj Selvin
  • 1,911
  • 22
  • 18
3

Try something like this: http://jsfiddle.net/D7E3E/4/

Using a container with overflow: hidden

EDIT: @Dominic Green beat me.

woutr_be
  • 9,242
  • 24
  • 71
  • 123
  • Thanks. it worked, but it crops the image from **top**. (see this: http://jsfiddle.net/x86Q7/ ) Isn't there any way to crop image from **center**? – Mahdi Ghiasi Aug 01 '12 at 10:52
  • Might be rather difficult with CSS, this is the best I could come up with http://jsfiddle.net/D7E3E/5/ – woutr_be Aug 01 '12 at 10:56
  • Yes, to get it centered correctly, you should use jQuery, might be a lot easier. – woutr_be Aug 01 '12 at 10:59
3

I think it's quite late for this answer. Anyway hope this will help somebody in the future. I faced the problem positioning the cards in angular. There are cards displayed for array of events. If image width of the event is big for card, the image should be shown by cropping from two sides and height of 100 %. If image height is long, images' bottom part is cropped and width is 100 %. Here is my pure css solution for this:

enter image description here

HTML:

 <span class="block clear img-card b-b b-light text-center" [ngStyle]="{'background-image' : 'url('+event.image+')'}"></span>

CSS

.img-card {
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
width: 100%;
overflow: hidden;
}
Nodira
  • 636
  • 1
  • 9
  • 22
  • i can't fathom how this works but it does. You need to position the span absolutely top:0;right:0;bottom:0;left:0 inside the relatively positioned parent to dimension it. – Mike Jan 22 '19 at 17:19
  • Thank you for feedback dear Mike, I'm happy if this was helpful. Do you want me to update the answer with your comment? – Nodira Jan 24 '19 at 05:53
3

after reading StackOverflow answers the simple solution I got is

.profilePosts div {

background: url("xyz");
background-size: contain;
background-repeat: no-repeat;
width: x;
height: y;

}
Om Fuke
  • 253
  • 1
  • 3
  • 10
3

you can do it by 'flex' display. for me!:

.avatar-img {
    display: flex;
    justify-content: center;
    align-items: stretch;
    border-radius: 50%;
    border: 1px  solid #dee2e6;
    height: 5.5rem;
    width: 5.5rem;
    overflow: hidden;
}
.avatar-img > img {
    flex-grow: 1;
    object-fit: cover;
}
<div>
  <div class="avatar-img">
    <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSqczw3Fb_TYsj0hbPEy0u7Ay2bVq1KurD6hw&amp;usqp=CAU" alt="Test!'s profile photo">
  </div>
  <div class="avatar-img">
    <img src="https://i.pinimg.com/236x/a1/37/09/a137098873af3bf6180dd24cbe388ae9--flower-iphone-wallpaper-wallpapers-flowers.jpg" alt="Test!'s profile photo">
  </div>
</div>
2

To fit image in fullscreen try this:

background-repeat: round;

suyash1798
  • 51
  • 3
0
<div class="container">
     <img src="http://i.stack.imgur.com/2OrtT.jpg"/>
</div>

<style>
.container {
       width: 150px;
       height: 100px;
       overflow: hidden;
}
</style>
user3181614
  • 139
  • 7
0

As far as I know, there is a plugin to make this simple.

jQuery Plugin: Auto transform <img> into background style

<img class="fill" src="image.jpg" alt="Fill Image"></img>

<script>
    $("img.fill").img2bg();
</script>

Besides, this way also fulfills the accessibility needs. As this plugin will NOT remove your <img> tag from your codes, the screen reader still tells you the ALT text instead of skipping it.

lewishole
  • 551
  • 4
  • 11
0

you have to use background-size : cover in the css

js code

 <div>
   <div className={styles.banner}>banner</div>
 </div>

css code

.banner{
  background: 
    url("./images/home-bg.jpg");
  background-size: cover;
  height: 53rem;
  width: 100%;
}
  • object fit is not working
  • background-size: contain is also not working
Rohan Devaki
  • 2,271
  • 1
  • 12
  • 19