[javascript] simulate background-size:cover on <video> or <img>

How can I simulate the functionality of background-size:cover on an html element like <video> or <img>?

I'd like it to work like

background-size: cover;
background-position: center center;

This question is related to javascript jquery css

The answer is


To answer the comment from weotch that Timothy Ryan Carpenter's answer doesn't account for cover's centering of the background, I offer this quick CSS fix:

CSS:

margin-left: 50%;
transform: translateX(-50%);

Adding these two lines will center any element. Even better, all browsers that can handle HTML5 video also support CSS3 transformations, so this will always work.

The complete CSS looks like this.

#video-background { 
    position: absolute;
    bottom: 0px; 
    right: 0px; 
    min-width: 100%; 
    min-height: 100%; 
    width: auto; 
    height: auto; 
    z-index: -1000; 
    overflow: hidden;
    margin-left: 50%;
    transform: translateX(-50%);
}

I'd have commented directly on Timothy's answer, but I don't have enough reputation to do so.


Right after our long comment section, I think this is what you're looking for, it's jQuery based:

HTML:

<img width="100%" id="img" src="http://uploads8.wikipaintings.org/images/william-adolphe-bouguereau/self-portrait-presented-to-m-sage-1886.jpg">

JS:

<script type="text/javascript">
window.onload = function(){
       var img = document.getElementById('img')
       if(img.clientHeight<$(window).height()){
            img.style.height=$(window).height()+"px";
       }
       if(img.clientWidth<$(window).width()){
            img.style.width=$(window).width()+"px";
       } 
}
?</script>??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

CSS:

body{
    overflow: hidden;
}

?The code above is using the browsers width and height if you where doing this within a div, you would have to change it to something like this:

For Div:

HTML:

<div style="width:100px; max-height: 100px;" id="div">
     <img width="100%" id="img" src="http://uploads8.wikipaintings.org/images/william-adolphe-bouguereau/self-portrait-presented-to-m-sage-1886.jpg">
</div>

JS:

<script type="text/javascript">
window.onload = function(){
       var img = document.getElementById('img')
       if(img.clientHeight<$('#div').height()){
            img.style.height=$('#div').height()+"px";
       }
       if(img.clientWidth<$('#div').width()){
            img.style.width=$('#div').width()+"px";
       } 
}
?</script>????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

CSS:

div{
   overflow: hidden;
}

I should also state that I've only tested this is Google Chrome... here is a jsfiddle: http://jsfiddle.net/ADCKk/


object-fit: cover is the best answer with this IE, Safari polyfill.

https://github.com/constancecchen/object-fit-polyfill

It is supporting img, video and picture elements.


This is something I pulled my hair out over for a while, but I came across a great solution that doesn't use any script, and can achieve a perfect cover simulation on video with 5 lines of CSS (9 if you count selectors and brackets). This has 0 edge-cases in which it doesn't work perfectly, short of CSS3-compatibility.

You can see an example here (archived)

The problem with Timothy's solution, is that it doesn't handle scaling correctly. If the surrounding element is smaller than the video file, it isn't scaled down. Even if you give the video tag a tiny initial size, like 16px by 9px, auto ends up forcing it to a minimum of its native file-size. With the current top-voted solution on this page, it was impossible for me to have the video file scale down resulting in a drastic zoom effect.

If the aspect ratio of your video is known, however, such as 16:9, you can do the following:

.parent-element-to-video {
    overflow: hidden;
}
video {
    height: 100%;
    width: 177.77777778vh; /* 100 * 16 / 9 */
    min-width: 100%;
    min-height: 56.25vw; /* 100 * 9 / 16 */
}

If the video's parent element is set to cover the entire page (such as position: fixed; width: 100%; height: 100vh;), then the video will, too.

If you want the video centered as well, you can use the surefire centering approach:

/* merge with above css */
.parent-element-to-video {
    position: relative; /* or absolute or fixed */
}
video {
    position: absolute;
    left: 50%; /* % of surrounding element */
    top: 50%;
    transform: translate(-50%, -50%); /* % of current element */
}

Of course, vw, vh, and transform are CSS3, so if you need compatibility with much older browsers, you'll need to use script.


i'm gunna post this solution as well, since i had this problem but the other solutions did not work for my situation...

i think to properly simulate the background-size:cover; css property on an element instead of an elements background-image property, you'd have to compare the images aspect ratio to the current windows aspect ratio, so no matter what size (and also in case the image is taller than wider) the window is the element is filling the window (and also centering it, though i don't know if that was a requirement)....

using an image, just for simplicity's sake, i'm sure a video element would work fine too.

first get the elements aspect ratio (once it's loaded), then attach the window resize handler, trigger it once for initial sizing:

var img = document.getElementById( "background-picture" ),
    imgAspectRatio;

img.onload = function() {
    // get images aspect ratio
    imgAspectRatio = this.height / this.width;
    // attach resize event and fire it once
    window.onresize = resizeBackground;
    window.onresize();
}

then in your resize handler you should first determine whether to fill width or fill height by comparing the window's current aspect ratio to the image's original aspect ratio.

function resizeBackground( evt ) {

// get window size and aspect ratio
var windowWidth = window.innerWidth,
    windowHeight = window.innerHeight;
    windowAspectRatio = windowHeight / windowWidth;

//compare window ratio to image ratio so you know which way the image should fill
if ( windowAspectRatio < imgAspectRatio ) {
    // we are fill width
    img.style.width = windowWidth + "px";
    // and applying the correct aspect to the height now
    img.style.height = (windowWidth * imgAspectRatio) + "px";
    // this can be margin if your element is not positioned relatively, absolutely or fixed
    // make sure image is always centered
    img.style.left = "0px";
    img.style.top = (windowHeight - (windowWidth * imgAspectRatio)) / 2 + "px";
} else { // same thing as above but filling height instead
    img.style.height = windowHeight + "px";
    img.style.width = (windowHeight / imgAspectRatio) + "px";
    img.style.left = (windowWidth - (windowHeight / imgAspectRatio)) / 2 + "px";
    img.style.top = "0px";
}

}


This approach just uses css and html. You can actually stack a divs below the video easily. It is cover but not centered while you resize.

HTML:

<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css"> 
</script>
</head>
<body>
<div id = "contain">
<div id="vid">
    <video autoplay>
        <source src="http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4" type="video/mp4" />
    </video>
</div>
</div>
</body>
</html>

CCS:

/*
filename:style.css
*/
body {
    margin:0;
}

#vid video{
position: absolute; 
right: 0; 
top: 0;
min-width: 100%; 
min-height: 100%;
width: auto; 
height: auto; 
}

#contain {
width:100%;
height:100%;
zoom:1%;/*Without this the video will be stretched and skewed*/ 
}

jsFiddle

Using background cover is fine for images, and so is width 100%. These are not optimal for <video>, and these answers are overly complicated. You do not need jQuery or JavaScript to accomplish a full width video background.

Keep in mind that my code will not cover a background completely with a video like cover will, but instead it will make the video as big as it needs to be to maintain aspect ratio and still cover the whole background. Any excess video will bleed off the page edge, which sides depend on where you anchor the video.

The answer is quite simple.

Just use this HTML5 video code, or something along these lines: (test in Full Page)

_x000D_
_x000D_
html, body {_x000D_
  width: 100%; _x000D_
  height:100%; _x000D_
  overflow:hidden;_x000D_
}_x000D_
_x000D_
#vid{_x000D_
  position: absolute;_x000D_
  top: 50%; _x000D_
  left: 50%;_x000D_
  -webkit-transform: translateX(-50%) translateY(-50%);_x000D_
  transform: translateX(-50%) translateY(-50%);_x000D_
  min-width: 100%; _x000D_
  min-height: 100%; _x000D_
  width: auto; _x000D_
  height: auto;_x000D_
  z-index: -1000; _x000D_
  overflow: hidden;_x000D_
}
_x000D_
<video id="vid" video autobuffer autoplay>_x000D_
  <source id="mp4" src="http://grochtdreis.de/fuer-jsfiddle/video/sintel_trailer-480.mp4" type="video/mp4">_x000D_
</video>
_x000D_
_x000D_
_x000D_

The min-height and min-width will allow the video to maintain the aspect ratio of the video, which is usually the aspect ratio of any normal browser at a normal resolution. Any excess video bleeds off the side of the page.


@Hidden Hobbes

This question has an open bounty worth +100 reputation from Hidden Hobbes ending in 6 days. Inventive use of viewport units to obtain a flexible CSS only solution.

You opened a bounty on this question for a CSS only solution, so I will give it a try. My solution to a problem like this is to use a fixed ratio to decide the height and width of the video. I usually use Bootstrap, but I extracted the necessary CSS from there to make it work without. This is a code I have used earlier to among other things center an embeded video with the correct ratio. It should work for <video> and <img> elements too It's the top one that is relevant here, but I gave you the other two as well since I already had them laying around. Best of luck! :)

jsfiddle fullscreen example

_x000D_
_x000D_
.embeddedContent.centeredContent {_x000D_
    margin: 0px auto;_x000D_
}_x000D_
.embeddedContent.rightAlignedContent {_x000D_
    margin: auto 0px auto auto;_x000D_
}_x000D_
.embeddedContent > .embeddedInnerWrapper {_x000D_
    position:relative;_x000D_
    display: block;_x000D_
    padding: 0;_x000D_
    padding-top: 42.8571%; /* 21:9 ratio */_x000D_
}_x000D_
.embeddedContent > .embeddedInnerWrapper > iframe {_x000D_
    position: absolute;_x000D_
    top: 0;_x000D_
    left: 0;_x000D_
    bottom: 0;_x000D_
    height: 100%;_x000D_
    width: 100%;_x000D_
    border: 0;_x000D_
}_x000D_
.embeddedContent {_x000D_
    max-width: 300px;_x000D_
}_x000D_
.box1text {_x000D_
    background-color: red;_x000D_
}_x000D_
/* snippet from Bootstrap */_x000D_
.container {_x000D_
    margin-right: auto;_x000D_
    margin-left: auto;_x000D_
}_x000D_
.col-md-12 {_x000D_
    width: 100%;_x000D_
}
_x000D_
<div class="container">_x000D_
    <div class="row">_x000D_
        <div class="col-md-12">_x000D_
            Testing ratio AND left/right/center align:<br />_x000D_
            <div class="box1text">_x000D_
                <div class="embeddedContent centeredContent">_x000D_
                    <div class="embeddedInnerWrapper">_x000D_
                        <iframe allowfullscreen="true" allowscriptaccess="always" frameborder="0" height="349" scrolling="no" src="//www.youtube.com/embed/u6XAPnuFjJc?wmode=transparent&amp;jqoemcache=eE9xf" width="425"></iframe>_x000D_
                    </div>_x000D_
                </div>_x000D_
            </div>_x000D_
        </div>_x000D_
    </div>_x000D_
</div>_x000D_
<div class="container">_x000D_
    <div class="row">_x000D_
        <div class="col-md-12">_x000D_
            Testing ratio AND left/right/center align:<br />_x000D_
            <div class="box1text">_x000D_
                <div class="embeddedContent rightAlignedContent">_x000D_
                    <div class="embeddedInnerWrapper">_x000D_
                        <iframe allowfullscreen="true" allowscriptaccess="always" frameborder="0" height="349" scrolling="no" src="//www.youtube.com/embed/u6XAPnuFjJc?wmode=transparent&amp;jqoemcache=eE9xf" width="425"></iframe>_x000D_
                    </div>_x000D_
                </div>_x000D_
            </div>_x000D_
        </div>_x000D_
    </div>_x000D_
</div>_x000D_
<div class="container">_x000D_
    <div class="row">_x000D_
        <div class="col-md-12">_x000D_
            Testing ratio AND left/right/center align:<br />_x000D_
            <div class="box1text">_x000D_
                <div class="embeddedContent">_x000D_
                    <div class="embeddedInnerWrapper">_x000D_
                        <iframe allowfullscreen="true" allowscriptaccess="always" frameborder="0" height="349" scrolling="no" src="//www.youtube.com/embed/u6XAPnuFjJc?wmode=transparent&amp;jqoemcache=eE9xf" width="425"></iframe>_x000D_
                    </div>_x000D_
                </div>_x000D_
            </div>_x000D_
        </div>_x000D_
    </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


Old question, but in case anyone sees this, the best answer in my opinion is to convert the video into an animated GIF. This gives you much more control and you can just treat it like an image. It's also the only way for it to work on mobile, since you can't autoplay videos. I know the question is asking to do it in an <img> tag, but I don't really see the downside of using a <div> and doing background-size: cover


For some browsers you can use

object-fit: cover;

http://caniuse.com/object-fit


Based on Daniel de Wit's answer and comments, I searched a bit more. Thanks to him for the solution.

The solution is to use object-fit: cover; which has a great support (every modern browser support it). If you really want to support IE, you can use a polyfill like object-fit-images or object-fit.

Demos :

_x000D_
_x000D_
img {_x000D_
  float: left;_x000D_
  width: 100px;_x000D_
  height: 80px;_x000D_
  border: 1px solid black;_x000D_
  margin-right: 1em;_x000D_
}_x000D_
.fill {_x000D_
  object-fit: fill;_x000D_
}_x000D_
.contain {_x000D_
  object-fit: contain;_x000D_
}_x000D_
.cover {_x000D_
  object-fit: cover;_x000D_
}_x000D_
.none {_x000D_
  object-fit: none;_x000D_
}_x000D_
.scale-down {_x000D_
  object-fit: scale-down;_x000D_
}
_x000D_
<img class="fill" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>_x000D_
<img class="contain" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>_x000D_
<img class="cover" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>_x000D_
<img class="none" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>_x000D_
<img class="scale-down" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
_x000D_
_x000D_
_x000D_

and with a parent:

_x000D_
_x000D_
div {_x000D_
  float: left;_x000D_
  width: 100px;_x000D_
  height: 80px;_x000D_
  border: 1px solid black;_x000D_
  margin-right: 1em;_x000D_
}_x000D_
img {_x000D_
  width: 100%;_x000D_
  height: 100%;_x000D_
}_x000D_
.fill {_x000D_
  object-fit: fill;_x000D_
}_x000D_
.contain {_x000D_
  object-fit: contain;_x000D_
}_x000D_
.cover {_x000D_
  object-fit: cover;_x000D_
}_x000D_
.none {_x000D_
  object-fit: none;_x000D_
}_x000D_
.scale-down {_x000D_
  object-fit: scale-down;_x000D_
}
_x000D_
<div>_x000D_
<img class="fill" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>_x000D_
</div><div>_x000D_
<img class="contain" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>_x000D_
</div><div>_x000D_
<img class="cover" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>_x000D_
</div><div>_x000D_
<img class="none" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>_x000D_
</div><div>_x000D_
<img class="scale-down" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>_x000D_
</div>
_x000D_
_x000D_
_x000D_


The top answer doesn't scale down the video when you're at browser widths of less than your video's width. Try using this CSS (with #bgvid being your video's id):

#bgvid {
     position: fixed;
     top: 50%;
     left: 50%;
     min-width: 100%;
     min-height: 100%;
     width: auto;
     height: auto;
     transform: translateX(-50%) translateY(-50%);
     -webkit-transform: translateX(-50%) translateY(-50%);
}

CSS and little js can make the video cover the background and horizontally centered.

CSS:

video#bgvid {
    position: absolute;
    bottom: 0px; 
    left: 50%; 
    min-width: 100%; 
    min-height: 100%; 
    width: auto; 
    height: auto; 
    z-index: -1; 
    overflow: hidden;
}

JS: (bind this with window resize and call once seperately)

$('#bgvid').css({
    marginLeft : '-' + ($('#bgvid').width()/2) + 'px'
})

The other answers were good but they involve javascript or they doesn't center the video horizontally AND vertically.

You can use this full CSS solution to have a video that simulate the background-size: cover property:

  video {
    position: fixed;           // Make it full screen (fixed)
    right: 0;
    bottom: 0;
    z-index: -1;               // Put on background

    min-width: 100%;           // Expand video
    min-height: 100%;
    width: auto;               // Keep aspect ratio
    height: auto;

    top: 50%;                  // Vertical center offset
    left: 50%;                 // Horizontal center offset

    -webkit-transform: translate(-50%,-50%);
    -moz-transform: translate(-50%,-50%);
    -ms-transform: translate(-50%,-50%);
    transform: translate(-50%,-50%);         // Cover effect: compensate the offset

    background: url(bkg.jpg) no-repeat;      // Background placeholder, not always needed
    background-size: cover;
  }

I just solved this and wanted to share. This works with Bootstrap 4. It works with img but I didn't test it with video. Here is the HAML and SCSS

HAML
.container
  .detail-img.d-flex.align-items-center
    %img{src: 'http://placehold.it/1000x700'}
SCSS
.detail-img { // simulate background: center/cover
  max-height: 400px;
  overflow: hidden;

  img {
    width: 100%;
  }
}

_x000D_
_x000D_
/* simulate background: center/cover */_x000D_
.center-cover { _x000D_
  max-height: 400px;_x000D_
  overflow: hidden;_x000D_
  _x000D_
}_x000D_
_x000D_
.center-cover img {_x000D_
    width: 100%;_x000D_
}
_x000D_
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>_x000D_
<div class="container">_x000D_
  <div class="center-cover d-flex align-items-center">_x000D_
    <img src="http://placehold.it/1000x700">_x000D_
  </div>_x000D_
</div>
_x000D_
_x000D_
_x000D_


M-Pixel's solution is great in that it solves the scaling problem of Timothy's answer (the video will scale up but not down, so if your video is really large there are good chances you will only see a small zoomed in part of it). However, that solution is based on false assumptions related to the size of the video container, namely that it is necessarily 100% of the viewport's width and height. I have found a few cases where it didn't work for me, so I decided to tackle the problem myself, and I believe I came up with the ultimate solution.

HTML

<div class="parent-container">
    <div class="video-container">
        <video width="1920" height="1080" preload="auto" autoplay loop>
            <source src="video.mp4" type="video/mp4">
        </video>
    </div>
</div>

CSS

.parent-container {
  /* any width or height */
  position: relative;
  overflow: hidden;
}
.video-container {
  width: 100%;
  min-height: 100%;
  position: absolute;
  left: 0px;
  /* center vertically */
  top: 50%;
  -moz-transform: translate(0%, -50%);
  -ms-transform: translate(0%, -50%);
  -webkit-transform: translate(0%, -50%);
  transform: translate(0%, -50%);
}
.video-container::before {
  content: "";
  display: block;
  height: 0px;
  padding-bottom: 56.25%; /* 100% * 9 / 16 */
}
.video-container video {
  width: auto;
  height: 100%;
  position: absolute;
  top: 0px;
  /* center horizontally */
  left: 50%;
  -moz-transform: translate(-50%, 0%);
  -ms-transform: translate(-50%, 0%);
  -webkit-transform: translate(-50%, 0%);
  transform: translate(-50%, 0%);
}

It is also based on the ratio of the video, so if your video has a ratio other than 16 / 9 you will want to change the padding-bottom %. Other than that, it works out of the box. Tested in IE9+, Safari 9.0.1, Chrome 46, and Firefox 41.

EDIT (March 17, 2016)

Since I posted this answer I've written a small CSS module to simulate both background-size: cover and background-size: contain on <video> elements: http://codepen.io/benface/pen/NNdBMj

It supports different alignments for the video (similar to background-position). Also note that the contain implementation is not perfect. Unlike background-size: contain, it won't scale the video past its actual size if the container's width and height are bigger, but I think it can still be useful in some cases. I've also added special fill-width and fill-height classes that you can use together with contain to get a special mix of contain and cover... try it out, and feel free to improve it!


Guys I have a better solution its short and works perfectly to me. I used it to video. And its perfectly emulates the cover option in css.

Javascript

    $(window).resize(function(){
            //use the aspect ration of your video or image instead 16/9
            if($(window).width()/$(window).height()>16/9){
                $("video").css("width","100%");
                $("video").css("height","auto");
            }
            else{
                $("video").css("width","auto");
                $("video").css("height","100%");
            }
    });

If you flip the if, else you will get contain.

And here is the css. (You don't need to use it if you don't want center positioning, the parent div must be "position:relative")

CSS

video {
position: absolute;
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
top: 50%;
left: 50%;}

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

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