[css] CSS Image size, how to fill, but not stretch?

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.

This question is related to css image

The answer is


To fit image in fullscreen try this:

background-repeat: round;


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;
}

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;
}

CSS solution no JS and no background image:

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

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

http://jsfiddle.net/5xjr05dt/

Method 2 "transform" ( IE9+ ):

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

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! ):

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

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

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

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

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


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();

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.

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

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.


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

<style>
.container {
       width: 150px;
       height: 100px;
       overflow: hidden;
}
</style>

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 ..."  />
    

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.


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;

}

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/


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!


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/


  • 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%);
}

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

Using a container with overflow: hidden

EDIT: @Dominic Green beat me.