42

I would like to use a video as background in CSS3. I know that there is no background-video property, but is it possible to do this behavior. Using a fullsize video-tag doesn't give the wanted result, cause there is content that need to be displayed over the video.

It need to be non JS. If it is not possible then I need to do changes on my serverside an give as result also a screenshot of the video.

I need the video to replace the colored boxes:

Boxes

The colored boxes are atm just, CSS boxes.

Knerd
  • 1,892
  • 3
  • 28
  • 55

3 Answers3

48

Pure CSS method

It is possible to center a video inside an element just like a cover sized background-image without JS using the object-fit attribute or CSS Transforms.

2021 answer: object-fit

As pointed in the comments, it is possible to achieve the same result without CSS transform, but using object-fit, which I think it's an even better option for the same result:

.video-container {
    height: 300px;
    width: 300px;
    position: relative;
}

.video-container video {
  width: 100%;
  height: 100%;
  position: absolute;
  object-fit: cover;
  z-index: 0;
}

/* Just styling the content of the div, the *magic* in the previous rules */
.video-container .caption {
  z-index: 1;
  position: relative;
  text-align: center;
  color: #dc0000;
  padding: 10px;
}
<div class="video-container">
    <video autoplay muted loop>
        <source src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4" />
    </video>
    <div class="caption">
      <h2>Your caption here</h2>
    </div>
</div>

Previous answer: CSS Transform

You can set a video as a background to any HTML element easily thanks to transform CSS property.

Note that you can use the transform technique to center vertically and horizontally any HTML element.

.video-container {
  height: 300px;
  width: 300px;
  overflow: hidden;
  position: relative;
}

.video-container video {
  min-width: 100%;
  min-height: 100%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translateX(-50%) translateY(-50%);
}

/* Just styling the content of the div, the *magic* in the previous rules */
.video-container .caption {
  z-index: 1;
  position: relative;
  text-align: center;
  color: #dc0000;
  padding: 10px;
}
<div class="video-container">
  <video autoplay muted loop>
    <source src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4" />
  </video>
  <div class="caption">
    <h2>Your caption here</h2>
  </div>
</div>
campsjos
  • 1,275
  • 15
  • 22
  • 2
    This is clever thinking. I was able to add `scale(2)` to the transform, and add an `overflow: hidden;` to the container div to achieve the full size responsive clipped video background I was looking for. – lakewood May 16 '19 at 15:43
  • 7
    This is actually the correct answer to this question! – stamat Jun 18 '19 at 12:23
  • 2
    @vars you can use object-fit: cover; on the video tag to make it fullscreen. This way you can easily position the video as well (object-position: center center;) – ElBrm Dec 17 '19 at 14:06
  • 1
    One suggested modification to the above code is adding playsinline to the video tag e.g. ` – user3220812 May 31 '20 at 21:35
  • 2
    I had to add the following to get this working: width: 100%; height: 100%; object-fit: cover; – Andy P Sep 10 '20 at 14:32
  • 1
    undoubtedly the optimal answer to the problem. Adjust the % of translate X or Y better positioning you video(based on the portion you want to show) and you're fine. +1 (really nice solution) – Andrea_86 Oct 28 '20 at 09:43
  • 2
    The way to go: width: 100%; height: 100%; object-fit: cover; object-position: center center; – pixelearth Feb 10 '21 at 07:01
  • You are right @pixelearth, object-fit is super useful in this situation. I will update my answer when I have some time. Thanks! – campsjos Feb 10 '21 at 17:44
  • Does this solution works on mobile devices? I have implemented it and the video shrinks on small screens. BTW, I am trying to use this solution in the following vertical container stack: header -> video-container -> footer. – yaach Sep 22 '22 at 14:45
  • It should work, the only issue that you can find is that some mobile browsers do not allow media content to be played without user interaction (for example click on a play button to play a video). But in terms of display, this is common CSS, if the wrapper covers all the area you want, the absolute positioned video should do it too. – campsjos Sep 22 '22 at 17:01
25

Why not fix a <video> and use z-index:-1 to put it behind all other elements?

html, body { width:100%; height:100%; margin:0; padding:0; }

<div style="position: fixed; top: 0; width: 100%; height: 100%; z-index: -1;">
    <video id="video" style="width:100%; height:100%">
        ....
    </video>
</div>
<div class='content'>
    ....

Demo

If you want it within a container you have to add a container element and a little more CSS

/* HTML */
<div class='vidContain'>
    <div class='vid'>
        <video> ... </video>
    </div>
    <div class='content'> ... The rest of your content ... </div>
</div>

/* CSS */
.vidContain {
    width:300px; height:200px;
    position:relative;
    display:inline-block;
    margin:10px;
}
.vid {
    position: absolute; 
    top: 0; left:0;
    width: 100%; height: 100%; 
    z-index: -1;
}    
.content {
    position:absolute;
    top:0; left:0;
    background: black;
    color:white;
}

Demo

Zach Saucier
  • 24,871
  • 12
  • 85
  • 147
  • Doesn't work, I need the video to replace the colored boxes, see my edit :) – Knerd Jan 02 '14 at 20:59
  • 1
    @Knerd So use the same approach but add a container. I updated my answer – Zach Saucier Jan 05 '14 at 23:45
  • Oh sry, I just forgot again, but it does work now :) Thank you very much :) I just have a padding in my grid thing, but doesn't matter. – Knerd Jan 24 '14 at 19:32
  • Looks broken in Chrome. – AturSams Jul 11 '17 at 14:42
  • @zehelvion It still works just fine. The videos are not clickable, but that's not part of the question. You can add the `autoplay` attribute to see the video working. – Zach Saucier Jul 11 '17 at 15:00
  • First, thanks for the helpful replay. Second, this is not the main issue, the thing is that there's a whatchamacallit under the video, track bar? play button and such. – AturSams Jul 11 '17 at 16:12
  • I guess it just needs loop="loop" – AturSams Jul 11 '17 at 16:16
  • @zehelvion That's a completely different question. – Zach Saucier Jul 11 '17 at 17:27
  • I am pretty sure it's just a matter of having the `loop` option turned on. The common trend is to have the video background running endlessly (it is not uncommon). – AturSams Jul 13 '17 at 08:53
  • Also please notice that with the current css setup, at least on my machine and browser, the content is outside the div and not inside as I it was intended (hence I thought it was broken)... Here is what worked for me (obviously credits to you for the original setup): http://jsfiddle.net/M2DCk/377/ – AturSams Jul 13 '17 at 09:04
19

I believe this is what you're looking for. It automatically scaled the video to fit the container.

DEMO: http://jsfiddle.net/t8qhgxuy/

Video need to have height and width always set to 100% of the parent.

HTML:

<div class="one"> CONTENT OVER VIDEO
    <video class="video-background" no-controls autoplay src="https://dl.dropboxusercontent.com/u/8974822/cloud-troopers-video.mp4" poster="http://thumb.multicastmedia.com/thumbs/aid/w/h/t1351705158/1571585.jpg"></video>
</div>

<div class="two">
    <video class="video-background" no-controls autoplay src="https://dl.dropboxusercontent.com/u/8974822/cloud-troopers-video.mp4" poster="http://thumb.multicastmedia.com/thumbs/aid/w/h/t1351705158/1571585.jpg"></video> CONTENT OVER VIDEO
</div>

CSS:

body {
    overflow: scroll;
    padding:  60px 20px;
}

.one {
    width: 90%;
    height: 30vw;
    overflow: hidden;
    border: 15px solid red;
    margin-bottom: 40px;
    position: relative;
}

.two{
    width: 30%;
    height: 300px;
    overflow: hidden;
    border: 15px solid blue;
    position: relative;
}

.video-background { /* class name used in javascript too */
    width: 100%; /* width needs to be set to 100% */
    height: 100%; /* height needs to be set to 100% */
    position: absolute;
    left: 0;
    top: 0;
    z-index: -1;
}

JS:

function scaleToFill() {
    $('video.video-background').each(function(index, videoTag) {
       var $video = $(videoTag),
           videoRatio = videoTag.videoWidth / videoTag.videoHeight,
           tagRatio = $video.width() / $video.height(),
           val;

       if (videoRatio < tagRatio) {
           val = tagRatio / videoRatio * 1.02; <!-- size increased by 2% because value is not fine enough and sometimes leaves a couple of white pixels at the edges -->
       } else if (tagRatio < videoRatio) {
           val = videoRatio / tagRatio * 1.02;
       }

       $video.css('transform','scale(' + val  + ',' + val + ')');

    });    
}

$(function () {
    scaleToFill();

    $('.video-background').on('loadeddata', scaleToFill);

    $(window).resize(function() {
        scaleToFill();
    });
});
marcel_pi
  • 375
  • 1
  • 3
  • 7
  • 1
    Is it available without JavaScript? I would like a pure HTML and JS solution for the problem. – Knerd Jan 28 '15 at 09:35