166

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;
Mosh Feu
  • 24,625
  • 12
  • 74
  • 111
seron
  • 4,192
  • 5
  • 30
  • 50
  • 1
    okay, I've never used background-size: cover; but I looked at it online, so what your wanting is a way to have a fullscreen image / video which resizes when the window resizes? – Lennart May 29 '12 at 11:03
  • 1
    Yes, but there are subtleties with `cover`. See Background-size 101 on [link](http://www.onextrapixel.com/2012/03/02/using-css-background-size-responsively/). – seron May 29 '12 at 11:09
  • okay so to simplify 100% width of an image / video and if there as an overflow it gets cut? If you're wanting this I can see if I can code that, but for video you should keep in mind you would need a custom player because in most browsers the controls are at the bottom of the player and they would get cut of if there is an overflow ... – Lennart May 29 '12 at 11:26
  • Yes, overflow equally on opposite sides. I'm aware of the video controls issue. – seron May 29 '12 at 11:30
  • okay, what's wrong with just using width="100%" on an image? – Lennart May 29 '12 at 11:46
  • 1
    If the window is taller than the image it will leave empty space somewhere along the vertical axis, I think. In such a case the image should instead overflow on the sides and its height be the same as the window. And the converse should happen when the window is wider than the image. – seron May 29 '12 at 11:59
  • so in simple terms if image height is less than browser height make image fit to browser so it has the height of the browser – Lennart May 29 '12 at 12:06
  • For the record: what you're looking for is the css 'object-fit' property on a video element. It's poorly supported. – commonpike Mar 14 '14 at 16:51

18 Answers18

163

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.

Zsolt Meszaros
  • 8,506
  • 12
  • 20
  • 30
M-Pixel
  • 2,825
  • 2
  • 12
  • 24
  • 4
    This is the best answer. No javascript, pure CSS, scales correctly and centered. – mark.monteiro Mar 31 '16 at 15:48
  • 6
    Ah yeah man. This here is THE answer for 2016. Ignore all others. – Josh Burson Apr 06 '16 at 22:51
  • would you care to explain why this works ? I cant wrap my head around it. what do `vh` and `vw` have to do with anything ? – commonpike Apr 28 '16 at 12:15
  • `vw` and `vh` equate to "percentage of the viewport [width/height]". It works because you're using a percentage of the width to define the height (or vice versa) which isn't possible with the `%` unit. – M-Pixel Apr 30 '16 at 00:46
  • 1
    @insidesin: Post a fiddle? – M-Pixel Jun 27 '16 at 16:31
  • @Qwertman Look at your example, rescale the website and look for a fine white line that goes in and out at different sizes. Firefox. – insidesin Jun 29 '16 at 13:25
  • This is the correct answer by far. Amazing. A small improvement: If using the Youtube Iframe API, use `width: calc(110vh * 16 / 9);` and `min-height: calc(110vw * 9 / 16);` to hide the youtube logo. – incompleteness Jul 22 '16 at 00:09
  • Needs a fiddle, isn't reproducible for me –  Sep 05 '16 at 05:38
  • Wow, excellent! No JavaScript, no shims - just pure and 100% valid CSS. I tested it with Firefox 43.0.1, Chrome 53, IE 11, Opera 29.0 and Safari 10.0. But I'm sure it works with much older browsers too, since it is only pure CSS 3 support. – StanE Oct 06 '16 at 12:22
  • Very nice solution! But what if I don't know the aspect ratio? Is really necessary JS for unknown aspect ratio? – Jabel Márquez Aug 18 '17 at 15:57
  • The `width: auto` would make this solution bullet proof. IE9+ – thednp Sep 06 '17 at 09:02
  • @M-Pixel I can't make it work, here a simple fiddle: https://jsfiddle.net/jf00prjL/, what am I doing wrong ? – Allan Raquin Nov 22 '17 at 10:11
  • @AllanRaquin because this solution uses vh, it doesn't work with containers that are a different size from the viewport. – M-Pixel Dec 29 '17 at 15:12
  • 3
    In 2020, the best solution is object-fit: cover, as described in the answer by Daniël de Wit – Brett Donald Apr 08 '20 at 04:00
  • All this does is overscale the video more than it needs to be, I'm sure there's a dynamic option somewhere. – user67 Feb 06 '21 at 09:52
132

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.

Miro
  • 7,402
  • 2
  • 25
  • 52
  • 2
    This is far simpler than the other answers, and works fine for me. Just setting `min-width` or `min-height` does the trick. – Ryan Burney Sep 03 '13 at 17:15
  • 31
    This solution doesn't center the video like cover does. – weotch Oct 10 '13 at 18:04
  • 1
    just a comment to prevent newbies from pulling their hair out: #video_background{ should be #videobackground{. – carrabino Oct 28 '13 at 02:26
  • 1
    +10 for you ... i cannot upvote your answer enough ... thank you very much for posting this ... the trick that did it for me was bottom/right: 0. – carrabino Mar 06 '14 at 14:52
  • 1
    What is the z-index for ?!! – Armeen Harwood Aug 07 '14 at 02:38
  • The z-index moves the video to the background, placing it under any other content that might exist within the same parent tag. – kfriend Aug 27 '14 at 14:10
  • 21
    This doesn't scale down a video at all (I didn't try scaling one up), which causes numerous problems if the browser window is small, and the video is large. So basically it only takes care of the bleed part of the background-size: cover, not the scaling part. – Kevin Newman Oct 17 '14 at 18:17
  • 4
    With current technologies this should be the accepted answer: a CSS solution is preferable to a Javascript one. Even though it requires you to set your parentNode properly. For centering the video, use this: `position: absolute; left: 50%; top: 50%; transform: translateX(-50%) translateY(-50%);`. – Sjeiti Dec 14 '14 at 09:38
  • 1
    I just put this in, and found that with translate -50%, it was simply going off the page and was unviewable. I removed the negative signs on the translate functions and it actually seems to work pretty well. – Katana314 May 28 '15 at 21:27
  • @Sjeiti Complete agree, this is exactly what I did. Giving `position: absolute; left: 50%; top: 50%; transform: translateX(-50%) translateY(-50%); min-height: 100%; max-height: 100%;` makes it behaves identically to a centered background image with background-size: cover . – XstiX Aug 25 '15 at 02:08
  • 1
    Just a note to say that from what I can tell, this won't scale up a video if the user has a very large screen. I added an extra media query for that situation to just set the video width to 100%. – jonosl May 17 '16 at 06:38
  • This solution is also very useful for tags that uses srcset attribute for responsive images – Fabien Quatravaux Jun 13 '16 at 12:13
121

For some browsers you can use

object-fit: cover;

http://caniuse.com/object-fit

Daniël de Wit
  • 1,596
  • 1
  • 11
  • 13
  • 16
    This is a very powerful declaration that, if browsers adopted it, would put an end to a lot of woes with scaling things on websites. – Mike Kormendy Oct 26 '14 at 21:36
  • 1
    This is exactly what I was looking for! – Peter_Fretter Nov 10 '14 at 08:05
  • 3
    There is a polyfill for those browses that don't support it (yet): https://github.com/anselmh/object-fit – creimers Dec 02 '14 at 14:11
  • 7
    had to apply as well `height: 100%; width: 100%;`. thanks for this modern answer – Jossef Harush Nov 11 '16 at 10:08
  • I made an answer based on this one with [examples and informations](http://stackoverflow.com/a/40692082/1248177). Thank you for pointing out this feature! – aloisdg Nov 19 '16 at 11:07
  • Good old Microsoft, holding back technology yet again. What do you supposed they do all day? – AJB Mar 30 '17 at 00:57
  • I shared a more exhaustive answer based on object-fit with some examples [here](https://stackoverflow.com/a/40692082/1248177). – aloisdg Jun 12 '19 at 07:45
  • Ah, mad I read this after implementing the accepted answer haha. Ripped all of that code out and went with this (plus width/height 100%). IE11 can settle for an image background fallback. – addMitt Jan 05 '21 at 00:45
  • You made my day ! – Alex L. Jan 08 '21 at 13:06
43

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>
CDspace
  • 2,551
  • 17
  • 31
  • 35
seron
  • 4,192
  • 5
  • 30
  • 50
  • Why was this solution downvoted? For all intents and purposes it seems to solve the problem. – Jan Mar 06 '13 at 11:04
  • 2
    This is the best solution I've found for this issue. Thanks! – Chaser324 May 25 '13 at 16:39
  • 1
    This works great if the video is big and the window small, but will not work for me if the window is bigger than the video and the video needs upscaling. I added the min trick from @Timothy-Ryan-Carpenter ([answer down here](http://stackoverflow.com/questions/10797632/simulate-background-sizecover-on-video-or-img#answer-15515336)) to the video tag as : `video { min-width: 100%; min-height: 100%; }` and it works like a charm. – Alexandre DuBreuil Mar 09 '14 at 11:38
  • I found this approach useful as well, and packaged it as a simple jQuery plugin for any interested: https://github.com/aMoniker/jquery.videocover – Jim Greenleaf Oct 04 '14 at 01:47
  • Despite what @AlexandreDuBreuil says, this scales videos up just fine (see for yourself: http://fiddle.jshell.net/GCtMm/show/). This is definitely the best solution here. Shame it's so JS heavy compared to the other answer here, but that's what you need if you want `background-size: cover` for video. – Chuck Le Butt Apr 15 '15 at 16:36
  • @JimGreenleaf can you explain how your script is to be used? i'm trying like this: $("#video_id").videocover(); but the result is not cover. the video fits the screen but is not cropped, leaving exposed areas of the background. – brett May 20 '15 at 19:35
19

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 :

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

and with a parent:

div {
  float: left;
  width: 100px;
  height: 80px;
  border: 1px solid black;
  margin-right: 1em;
}
img {
  width: 100%;
  height: 100%;
}
.fill {
  object-fit: fill;
}
.contain {
  object-fit: contain;
}
.cover {
  object-fit: cover;
}
.none {
  object-fit: none;
}
.scale-down {
  object-fit: scale-down;
}
<div>
<img class="fill" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
</div><div>
<img class="contain" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
</div><div>
<img class="cover" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
</div><div>
<img class="none" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
</div><div>
<img class="scale-down" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
</div>
aloisdg
  • 16,342
  • 4
  • 73
  • 80
  • 1
    Best modern answer. – Routhinator Nov 30 '16 at 17:47
  • 1
    This is _the answer_ for anyone targeting modern browsers. Using `object-fit: cover` and `width` and `height` set to 100%, you get a proportionately-scaled `img` or `video` zoomed on center without any fuss. – phip Jun 12 '19 at 03:04
14

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;
  }
micred
  • 1,440
  • 1
  • 17
  • 19
  • This didn't work for me. The video didn't scale up to fullscreen. Can I see your html for this example? Is it just a video tag in the body? – matt Nov 05 '14 at 22:06
  • Really nice solution. It didn't work for me at first but it was probably something I missed cause when I copied and pasted your css, it worked! Thanks ;) – rafaelbiten May 15 '15 at 14:54
  • 2
    worked great for me. i just changed position:fixed to absolute – Assaf Katz Sep 09 '15 at 12:20
13

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!

Community
  • 1
  • 1
benface
  • 538
  • 6
  • 16
7

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.

fozuse
  • 687
  • 10
  • 24
4

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'
})
3

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/

alex
  • 438,662
  • 188
  • 837
  • 957
Lennart
  • 1,530
  • 4
  • 19
  • 38
  • The jsfiddle doesn't seem to do anything when I change the size of the Result frame, or the browser size. I tried this in Chrome. – seron May 29 '12 at 13:36
  • I've updated it, but i still have a slight issue that if you decrease the width to much it suddenly jumps... http://jsfiddle.net/ADCKk/1/ – Lennart May 29 '12 at 14:01
  • okay, sorry but I'm clueless, I've tried so many things I think i've confused myself, I'm not sure if it's possible... The script above only works when you refresh the page, to make it work when you resize a window you would need to use the window.resize event in js, but I can't get it working, maybe you can with that info :) good luck anyway – Lennart May 29 '12 at 14:37
3

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

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

}

bawwb
  • 143
  • 1
  • 4
1

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*/ 
}
1

@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

.embeddedContent.centeredContent {
    margin: 0px auto;
}
.embeddedContent.rightAlignedContent {
    margin: auto 0px auto auto;
}
.embeddedContent > .embeddedInnerWrapper {
    position:relative;
    display: block;
    padding: 0;
    padding-top: 42.8571%; /* 21:9 ratio */
}
.embeddedContent > .embeddedInnerWrapper > iframe {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    height: 100%;
    width: 100%;
    border: 0;
}
.embeddedContent {
    max-width: 300px;
}
.box1text {
    background-color: red;
}
/* snippet from Bootstrap */
.container {
    margin-right: auto;
    margin-left: auto;
}
.col-md-12 {
    width: 100%;
}
<div class="container">
    <div class="row">
        <div class="col-md-12">
            Testing ratio AND left/right/center align:<br />
            <div class="box1text">
                <div class="embeddedContent centeredContent">
                    <div class="embeddedInnerWrapper">
                        <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>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<div class="container">
    <div class="row">
        <div class="col-md-12">
            Testing ratio AND left/right/center align:<br />
            <div class="box1text">
                <div class="embeddedContent rightAlignedContent">
                    <div class="embeddedInnerWrapper">
                        <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>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<div class="container">
    <div class="row">
        <div class="col-md-12">
            Testing ratio AND left/right/center align:<br />
            <div class="box1text">
                <div class="embeddedContent">
                    <div class="embeddedInnerWrapper">
                        <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>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
Community
  • 1
  • 1
turbopipp
  • 1,193
  • 2
  • 11
  • 25
  • 1
    Thanks for the answer @turbopipp although I'm afraid you've misunderstood the reason for my bounty. I've raised it so I can award it to an existing answer, it just wont allow me to do so until the bounty has been active for 24 hours. Still, +1 for your efforts the percentage padding trick is a useful way to ensure an element retains the correct aspect ratio. – Hidden Hobbes Nov 11 '15 at 10:10
  • Aha, well it was no hassle really, and real nice of you to give bounty to already existing answers. I guess I should read up on the bounty system. :) Thanks – turbopipp Nov 11 '15 at 11:17
0

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.

Community
  • 1
  • 1
Jake Z
  • 99
  • 5
0

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

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

/* simulate background: center/cover */
.center-cover { 
  max-height: 400px;
  overflow: hidden;
  
}

.center-cover img {
    width: 100%;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
  <div class="center-cover d-flex align-items-center">
    <img src="http://placehold.it/1000x700">
  </div>
</div>
Chloe
  • 21,167
  • 37
  • 143
  • 289
0

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

D-Marc
  • 2,237
  • 4
  • 16
  • 25
  • This is a nice idea and in some cases worth a try. Only downside is that the *.gif is (in my case) larger in filesize. I converted a 2.5MB *.mpeg to a 16MB *.gif. – Henning Fischer Dec 21 '18 at 14:42
  • I agree, and often times the `.gif` is much larger in size, while also blurrier. My view has changed since I wrote this answer. It's a shame you can't combine the best of both. – D-Marc Dec 27 '18 at 19:28
  • I ended up with a (shortened) *.gif for mobile and a *.mp4 for desktop. – Henning Fischer Dec 28 '18 at 12:11