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?
There is actually quite a simple css solution which even works on IE8:
.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_
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:
.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_
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.
.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_
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.
.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_
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. :)
Following the same principle, you can also use it to emulate background-size: contain
:
.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_
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
.tall-img{_x000D_
margin-top:-50%;_x000D_
width:100%;_x000D_
}_x000D_
.wide-img{_x000D_
margin-left:-50%;_x000D_
height:100%;_x000D_
}
_x000D_
TO
.wide-img{_x000D_
margin-left:-42%;_x000D_
height:100%;_x000D_
}_x000D_
.tall-img{_x000D_
margin-top:-42%;_x000D_
width:100%;_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.
.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_
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%;
}
Source: Stackoverflow.com