[html] Is there an equivalent to background-size: cover and contain for image elements?

I have a site with many pages and different background pictures, and I display them from CSS like:

body.page-8 {
    background: url("../img/pic.jpg") no-repeat scroll center top #000;
    background-size: cover;
}

However, I want to show different (fullscreen) pictures on one page using <img> elements, and I want them to have the same properties as the above background-image: cover; property (the images cant be displayed from CSS, they must be displayed from the HTML document).

Normally I use:

div.mydiv img {
    width: 100%;
}

Or:

div.mydiv img {
    width: auto;
}

to make the picture full and responsive. However the picture shrinks too much (width: 100%) when the screen gets too narrow, and shows the body's background-color in the bottom screen. The other method, width: auto;, only makes the image full size and does not respond to the screen size.

Is there a way to display the image the same way that background-size: cover does?

This question is related to html image css

The answer is


There is actually quite a simple css solution which even works on IE8:

_x000D_
_x000D_
.container {_x000D_
  position: relative;_x000D_
  overflow: hidden;_x000D_
  /* Width and height can be anything. */_x000D_
  width: 50vw;_x000D_
  height: 50vh;_x000D_
}_x000D_
_x000D_
img {_x000D_
  position: absolute;_x000D_
  /* Position the image in the middle of its container. */_x000D_
  top: -9999px;_x000D_
  right: -9999px;_x000D_
  bottom: -9999px;_x000D_
  left: -9999px;_x000D_
  margin: auto;_x000D_
  /* The following values determine the exact image behaviour. */_x000D_
  /* You can simulate background-size: cover/contain/etc._x000D_
     by changing between min/max/standard width/height values._x000D_
     These values simulate background-size: cover_x000D_
  */_x000D_
  min-width: 100%;_x000D_
  min-height: 100%;_x000D_
}
_x000D_
<div class="container">_x000D_
    <img src="http://placehold.it/200x200" alt="" />_x000D_
</div>
_x000D_
_x000D_
_x000D_


background:url('/image/url/') right top scroll; 
background-size: auto 100%; 
min-height:100%;

encountered same exact symptops. above worked for me.


For IE you also need to include the second line - width: 100%;

.mydiv img {
    max-width: 100%;
    width: 100%;
}

I needed to emulate background-size: contain, but couldn't use object-fit due to the lack of support. My images had containers with defined dimensions and this ended up working for me:

_x000D_
_x000D_
.image-container {_x000D_
  height: 200px;_x000D_
  width: 200px;_x000D_
  overflow: hidden;_x000D_
  background-color: rebeccapurple;_x000D_
  border: 1px solid yellow;_x000D_
  position: relative;_x000D_
}_x000D_
_x000D_
.image {_x000D_
  max-height: 100%;_x000D_
  max-width: 100%;_x000D_
  margin: auto;_x000D_
  position: absolute;_x000D_
  transform: translate(-50%, -50%);_x000D_
  top: 50%;_x000D_
  left: 50%;_x000D_
}
_x000D_
<!-- wide -->_x000D_
<div class="image-container">_x000D_
  <img class="image" src="http://placehold.it/300x100">_x000D_
</div>_x000D_
_x000D_
<!-- tall -->_x000D_
<div class="image-container">_x000D_
  <img class="image" src="http://placehold.it/100x300">_x000D_
</div>
_x000D_
_x000D_
_x000D_


Assuming you can arrange to have a container element you wish to fill, this appears to work, but feels a bit hackish. In essence, I just use min/max-width/height on a larger area and then scale that area back into the original dimensions.

_x000D_
_x000D_
.container {_x000D_
  width: 800px;_x000D_
  height: 300px;_x000D_
  border: 1px solid black;_x000D_
  overflow:hidden;_x000D_
  position:relative;_x000D_
}_x000D_
.container.contain img {_x000D_
  position: absolute;_x000D_
  left:-10000%; right: -10000%; _x000D_
  top: -10000%; bottom: -10000%;_x000D_
  margin: auto auto;_x000D_
  max-width: 10%;_x000D_
  max-height: 10%;_x000D_
  -webkit-transform:scale(10);_x000D_
  transform: scale(10);_x000D_
}_x000D_
.container.cover img {_x000D_
  position: absolute;_x000D_
  left:-10000%; right: -10000%; _x000D_
  top: -10000%; bottom: -10000%;_x000D_
  margin: auto auto;_x000D_
  min-width: 1000%;_x000D_
  min-height: 1000%;_x000D_
  -webkit-transform:scale(0.1);_x000D_
  transform: scale(0.1);_x000D_
}
_x000D_
<h1>contain</h1>_x000D_
  <div class="container contain">_x000D_
    <img _x000D_
       src="https://www.google.de/logos/doodles/2014/european-parliament-election-2014-day-4-5483168891142144-hp.jpg" _x000D_
       />_x000D_
    <!-- 366x200 -->_x000D_
  </div>_x000D_
  <h1>cover</h1>_x000D_
  <div class="container cover">_x000D_
    <img _x000D_
       src="https://www.google.de/logos/doodles/2014/european-parliament-election-2014-day-4-5483168891142144-hp.jpg" _x000D_
       />_x000D_
    <!-- 366x200 -->_x000D_
  </div>
_x000D_
_x000D_
_x000D_


I know this is old, however many solutions I see above have an issue with the image/video being too large for the container so not actually acting like background-size cover. However, I decided to make "utility classes" so that it would work for images and videos. You simply give the container the class .media-cover-wrapper and the media item itself the class .media-cover

Then you have the following jQuery:

function adjustDimensions(item, minW, minH, maxW, maxH) {
  item.css({
  minWidth: minW,
  minHeight: minH,
  maxWidth: maxW,
  maxHeight: maxH
  });
} // end function adjustDimensions

function mediaCoverBounds() {
  var mediaCover = $('.media-cover');

  mediaCover.each(function() {
   adjustDimensions($(this), '', '', '', '');
   var mediaWrapper = $(this).parent();
   var mediaWrapperWidth = mediaWrapper.width();
   var mediaWrapperHeight = mediaWrapper.height();
   var mediaCoverWidth = $(this).width();
   var mediaCoverHeight = $(this).height();
   var maxCoverWidth;
   var maxCoverHeight;

   if (mediaCoverWidth > mediaWrapperWidth && mediaCoverHeight > mediaWrapperHeight) {

     if (mediaWrapperHeight/mediaWrapperWidth > mediaCoverHeight/mediaCoverWidth) {
       maxCoverWidth = '';
       maxCoverHeight = '100%';
     } else {
       maxCoverWidth = '100%';
       maxCoverHeight = '';
     } // end if

     adjustDimensions($(this), '', '', maxCoverWidth, maxCoverHeight);
   } else {
     adjustDimensions($(this), '100%', '100%', '', '');
   } // end if
 }); // end mediaCover.each
} // end function mediaCoverBounds

When calling it make sure to take care of page resizing:

mediaCoverBounds();

$(window).on('resize', function(){
  mediaCoverBounds();
});

Then the following CSS:

.media-cover-wrapper {
  position: relative;
  overflow: hidden;
}

.media-cover-wrapper .media-cover {
  position: absolute;
  z-index: -1;
  top: 50%;
  left: 50%;
  -ms-transform: translate(-50%, -50%);
  -moz-transform: translate(-50%, -50%);
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

Yeah it may require jQuery but it responds quite well and acts exactly like background-size: cover and you can use it on image and/or videos to get that extra SEO value.


What you could do is use the 'style' attribute to add the background image to the element, that way you will still be calling the image in the HTML but you will still be able to use the background-size: cover css behaviour:

HTML:

    <div class="image-div" style="background-image:url(yourimage.jpg)">
    </div>

CSS:

    .image-div{
    background-size: cover;
    }

This is how I add the background-size: cover behaviour to elements that I need to dynamically load into HTML. You can then use awesome css classes like background-position: center. boom


I found a simple solution to emulate both cover and contain, which is pure CSS, and works for containers with dynamic dimensions, and also doesn't make any restriction on the image ratio.

Note that if you don't need to support IE, or Edge before 16, then you better use object-fit.

background-size: cover

_x000D_
_x000D_
.img-container {_x000D_
  position: relative;_x000D_
  overflow: hidden;_x000D_
}_x000D_
_x000D_
.background-image {_x000D_
  position: absolute;_x000D_
  min-width: 1000%;_x000D_
  min-height: 1000%;_x000D_
  left: 50%;_x000D_
  top: 50%;_x000D_
  transform: translateX(-50%) translateY(-50%) scale(0.1);_x000D_
  z-index: -1;_x000D_
}
_x000D_
<div class="img-container">_x000D_
  <img class="background-image" src="https://picsum.photos/1024/768/?random">_x000D_
  <p style="padding: 20px; color: white; text-shadow: 0 0 10px black">_x000D_
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum._x000D_
  </p>_x000D_
</div>
_x000D_
_x000D_
_x000D_

The 1000% is used here in case the image natural size is bigger than the size it is being displayed. For example, if the image is 500x500, but the container is only 200x200. With this solution, the image will be resized to 2000x2000 (due to min-width/min-height), then scaled down to 200x200 (due to transform: scale(0.1)).

The x10 factor can be replaced by x100 or x1000, but it is usually not ideal to have a 2000x2000 image being rendered on a 20x20 div. :)

background-size: contain

Following the same principle, you can also use it to emulate background-size: contain:

_x000D_
_x000D_
.img-container {_x000D_
  position: relative;_x000D_
  overflow: hidden;_x000D_
  z-index: 0;_x000D_
}_x000D_
_x000D_
.background-image {_x000D_
  position: absolute;_x000D_
  max-width: 10%;_x000D_
  max-height: 10%;_x000D_
  left: 50%;_x000D_
  top: 50%;_x000D_
  transform: translateX(-50%) translateY(-50%) scale(10);_x000D_
  z-index: -1;_x000D_
}
_x000D_
<div style="background-color: black">_x000D_
  <div class="img-container">_x000D_
    <img class="background-image" src="https://picsum.photos/1024/768/?random">_x000D_
    <p style="padding: 20px; color: white; text-shadow: 0 0 10px black">_x000D_
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum._x000D_
    </p>_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Try setting both min-height and min-width, with display:block:

img {
    display:block;
    min-height:100%;
    min-width:100%;
}

(fiddle)

Provided your image's containing element is position:relative or position:absolute, the image will cover the container. However, it will not be centred.

You can easily centre the image if you know whether it will overflow horizontally (set margin-left:-50%) or vertically (set margin-top:-50%). It may be possible to use CSS media queries (and some mathematics) to figure that out.


im not allowed to 'add a comment' so doing this , but yea what Eru Penkman did is pretty much spot on , to get it like background cover all you need to do is change

_x000D_
_x000D_
.tall-img{_x000D_
    margin-top:-50%;_x000D_
    width:100%;_x000D_
}_x000D_
.wide-img{_x000D_
    margin-left:-50%;_x000D_
    height:100%;_x000D_
}
_x000D_
_x000D_
_x000D_

TO

_x000D_
_x000D_
.wide-img{_x000D_
    margin-left:-42%;_x000D_
    height:100%;_x000D_
}_x000D_
.tall-img{_x000D_
    margin-top:-42%;_x000D_
    width:100%;_x000D_
}
_x000D_
_x000D_
_x000D_


With CSS you can simulate object-fit: [cover|contain];. It's use transform and [max|min]-[width|height]. It's not perfect. That not work in one case: if the image is wider and shorter than the container.

_x000D_
_x000D_
.img-ctr{_x000D_
  background: red;/*visible only in contain mode*/_x000D_
  border: 1px solid black;_x000D_
  height: 300px;_x000D_
  width: 600px;_x000D_
  overflow: hidden;_x000D_
  position: relative;_x000D_
  display: block;_x000D_
}_x000D_
.img{_x000D_
  display: block;_x000D_
_x000D_
  /*contain:*/_x000D_
  /*max-height: 100%;_x000D_
  max-width: 100%;*/_x000D_
  /*--*/_x000D_
_x000D_
  /*cover (not work for images wider and shorter than the container):*/_x000D_
  min-height: 100%;_x000D_
  width: 100%;_x000D_
  /*--*/_x000D_
_x000D_
  position: absolute;_x000D_
  top: 50%;_x000D_
  left: 50%;_x000D_
  transform: translate(-50%, -50%);_x000D_
}
_x000D_
<p>Large square:_x000D_
<span class="img-ctr"><img class="img" src="http://placehold.it/1000x1000"></span>_x000D_
</p>_x000D_
<p>Small square:_x000D_
<span class="img-ctr"><img class="img" src="http://placehold.it/100x100"></span>_x000D_
</p>_x000D_
<p>Large landscape:_x000D_
<span class="img-ctr"><img class="img" src="http://placehold.it/2000x1000"></span>_x000D_
</p>_x000D_
<p>Small landscape:_x000D_
<span class="img-ctr"><img class="img" src="http://placehold.it/200x100"></span>_x000D_
</p>_x000D_
<p>Large portrait:_x000D_
<span class="img-ctr"><img class="img" src="http://placehold.it/1000x2000"></span>_x000D_
</p>_x000D_
<p>Small portrait:_x000D_
<span class="img-ctr"><img class="img" src="http://placehold.it/100x200"></span>_x000D_
</p>_x000D_
<p>Ultra thin portrait:_x000D_
<span class="img-ctr"><img class="img" src="http://placehold.it/200x1000"></span>_x000D_
</p>_x000D_
<p>Ultra wide landscape (images wider and shorter than the container):_x000D_
<span class="img-ctr"><img class="img" src="http://placehold.it/1000x200"></span>_x000D_
</p>
_x000D_
_x000D_
_x000D_


We can take ZOOM approach. We can assume that max 30% (or more upto 100%) can be the zooming effect if aspect image height OR width is less than the desired height OR width. We can hide the rest not needed area with overflow: hidden.

.image-container {
  width: 200px;
  height: 150px;
  overflow: hidden;
}
.stage-image-gallery a img {
  max-height: 130%;
  max-width: 130%;
  position: relative;
  top: 50%;
  left: 50%;
  transform: translateX(-50%) translateY(-50%);
}

This will adjust images with different width OR height.


No, you can't get it quite like background-size:cover but..

This approach is pretty damn close: it uses JavaScript to determine if the image is landscape or portrait, and applies styles accordingly.

JS

 $('.myImages img').load(function(){
        var height = $(this).height();
        var width = $(this).width();
        console.log('widthandheight:',width,height);
        if(width>height){
            $(this).addClass('wide-img');
        }else{
            $(this).addClass('tall-img');
        }
    });

CSS

.tall-img{
    margin-top:-50%;
    width:100%;
}
.wide-img{
    margin-left:-50%;
    height:100%;
}

http://jsfiddle.net/b3PbT/


Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to image

Reading images in python Numpy Resize/Rescale Image Convert np.array of type float64 to type uint8 scaling values Extract a page from a pdf as a jpeg How do I stretch an image to fit the whole background (100% height x 100% width) in Flutter? Angular 4 img src is not found How to make a movie out of images in python Load local images in React.js How to install "ifconfig" command in my ubuntu docker image? How do I display local image in markdown?

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width