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 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.
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)
html, body {
width: 100%;
height:100%;
overflow:hidden;
}
#vid{
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
z-index: -1000;
overflow: hidden;
}
<video id="vid" video autobuffer autoplay>
<source id="mp4" src="http://grochtdreis.de/fuer-jsfiddle/video/sintel_trailer-480.mp4" type="video/mp4">
</video>
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.
For some browsers you can use
object-fit: cover;
http://caniuse.com/object-fit
Here's how I did this. A working example is in this jsFiddle.
var min_w = 300; // minimum video width allowed
var vid_w_orig; // original video dimensions
var vid_h_orig;
jQuery(function() { // runs after DOM has loaded
vid_w_orig = parseInt(jQuery('video').attr('width'));
vid_h_orig = parseInt(jQuery('video').attr('height'));
$('#debug').append("<p>DOM loaded</p>");
jQuery(window).resize(function () { resizeToCover(); });
jQuery(window).trigger('resize');
});
function resizeToCover() {
// set the video viewport to the window size
jQuery('#video-viewport').width(jQuery(window).width());
jQuery('#video-viewport').height(jQuery(window).height());
// use largest scale factor of horizontal/vertical
var scale_h = jQuery(window).width() / vid_w_orig;
var scale_v = jQuery(window).height() / vid_h_orig;
var scale = scale_h > scale_v ? scale_h : scale_v;
// don't allow scaled width < minimum video width
if (scale * vid_w_orig < min_w) {scale = min_w / vid_w_orig;};
// now scale the video
jQuery('video').width(scale * vid_w_orig);
jQuery('video').height(scale * vid_h_orig);
// and center it by scrolling the video viewport
jQuery('#video-viewport').scrollLeft((jQuery('video').width() - jQuery(window).width()) / 2);
jQuery('#video-viewport').scrollTop((jQuery('video').height() - jQuery(window).height()) / 2);
// debug output
jQuery('#debug').html("<p>win_w: " + jQuery(window).width() + "</p>");
jQuery('#debug').append("<p>win_h: " + jQuery(window).height() + "</p>");
jQuery('#debug').append("<p>viewport_w: " + jQuery('#video-viewport').width() + "</p>");
jQuery('#debug').append("<p>viewport_h: " + jQuery('#video-viewport').height() + "</p>");
jQuery('#debug').append("<p>video_w: " + jQuery('video').width() + "</p>");
jQuery('#debug').append("<p>video_h: " + jQuery('video').height() + "</p>");
jQuery('#debug').append("<p>vid_w_orig: " + vid_w_orig + "</p>");
jQuery('#debug').append("<p>vid_h_orig: " + vid_h_orig + "</p>");
jQuery('#debug').append("<p>scale: " + scale + "</p>");
};
#video-viewport {
position: absolute;
top: 0;
overflow: hidden;
z-index: -1; /* for accessing the video by click */
}
#debug {
position: absolute;
top: 0;
z-index: 100;
color: #fff;
font-size: 12pt;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="video-viewport">
<video autoplay controls preload width="640" height="360">
<source src="http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4"type="video/mp4" />
<source src="http://www.quirksmode.org/html5/videos/big_buck_bunny.webm"type="video/webm" />
<source src="http://www.quirksmode.org/html5/videos/big_buck_bunny.ogv"type="video/webm" />
</video>
</div>
<div id="debug"></div>