49

Has anyone been able to successfully resize a video element to a parent div?

My video element contains a webcam stream that comes in with a ratio of 4:3. I'd like to break the ratio and adjust it to the div size. I've tried the following:

  • Set width and height 100% > this doesn't do anything, 4:3 remains
  • Set min-height and min-width 100% > this makes the video resize to something really huge that overflows the div
  • position:absolute, bottom, top, left and right: 0px also a huge flow over the parent div
  • Using javascript to get the parent divs height and width, then setting it for the video: No effect, 4:3 ratio remains, no size change.

How to do it?

EDIT: Thanks Gaurav for that greatly detailed reply. It looks good, I wish it would work for me though.

.parentDiv // Results in around 400x400 pixels for me
{
    position: absolute;
    top: 11px;
    right: 10px;
    left: 10px;
    height: -webkit-calc(50% - 18px);
    height: calc(50% - 18px); 
    display: block;
} 

My video element is in there, I gave it your CSS solution. Unfortunately it only turned white. Could my parentDiv css have anything to do with that?

EDIT 2: Here's the HTML:

<div class="parentDiv"> 
    <video class="cam_video" autoplay></video>                      
</div>

This is mainly it . The src-attribute of the video is set to my webcam stream.

EDIT 3:

If I right-click and inspect the white (now red scribbled) part in this screenshot https://s22.postimg.cc/th4ha8nmp/ratio2.png, Chrome shows me that the white also belongs to the stream.

It seems as if the stream of the webcam comes along with white stripes at the top and bottom. This is.. annoying.

Cœur
  • 37,241
  • 25
  • 195
  • 267
spacecoyote
  • 1,909
  • 3
  • 19
  • 24

9 Answers9

46

1) CSS only

Demo

HTML

<div class="wrapper">
  <video class="videoInsert">
  <source src="http://www.w3schools.com/html/movie.mp4" type="video/mp4">
  <source src="movie.ogg" type="video/ogg">
  Your browser does not support the video tag.
 </video>
</div>

css

.videoInsert {
    position: absolute; 
    right: 0; 
    bottom: 0;
    min-width: 100%; 
    min-height: 100%;
    width: auto; 
    height: auto; 
    z-index: -100;
    background-size: cover;
    overflow: hidden;
}

2) jQuery

Demo

HTML

<div id="video-viewport">
    <video autoplay preload width="640" height="360">
        <source src="https://s3.amazonaws.com/whiteboard.is/videos/bg-loop-new.mp4" />
    </video>
</div>

css

#video-viewport {
    position: absolute;
    top: 0;
    left:0;
    overflow: hidden;
    z-index: -1; /* for accessing the video by click */
}
body{
    margin:0;
}

jquery

from this answer - simulate background-size:cover on <video> or <img>

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

3) using iframe css only

Demo

HTML

<div class="wrapper">
    <div class="h_iframe">
        <iframe src="//www.youtube.com/embed/9KunP3sZyI0" frameborder="0" allowfullscreen></iframe>
    </div>
</div>

css

.h_iframe iframe {
  position:absolute;
  top:0;
  left:0;
  width:100%; 
  height:100%;
}
Community
  • 1
  • 1
4dgaurav
  • 11,360
  • 4
  • 32
  • 59
  • 2
    Thanks for that! :) Unfortunately it didn't work for me. I updated my question with more information. Is my parentDiv wrong? I'll try your jQuery approach next. – spacecoyote Apr 23 '14 at 15:54
  • can you also provide me with your html? – 4dgaurav Apr 23 '14 at 15:56
  • Updated. There's usually also an img in the div before the webcam stream is shown. I remove that when the stream is shown, I left that out now. – spacecoyote Apr 23 '14 at 16:03
  • Could it be the lack of an explicite width and height and instead using calc that causes my problem? http://s30.postimg.org/43drs7br5/ratio.png The div is calculated right, at least. There it is with a 1px border. – spacecoyote Apr 23 '14 at 16:08
  • if you want a full screen video then NO, because, your height is 50% - 18px i.e. it is subtracting 18px from the 50% height of the screen. Then you have margin also. One more point you have nothing for width thus it is by default auto, not allowing to change its aspect ratio. – 4dgaurav Apr 23 '14 at 16:14
  • Thanks again. The parentDiv is 50%-18px of its own parent div. It's as big as in the screenshot above, parentDiv is the one with the border. The video won't scale up to it. I'm going to assume that it's related to not having an explicite width and investigate some more. – spacecoyote Apr 23 '14 at 16:19
  • None of these solutions are very good. Instead of the video resizing, things are cropped in both directions including the controls, especially when you shrink stuff. This may be good for images if you don't care about it being chopped up, but no good for video. – MC9000 Aug 01 '19 at 01:54
14

You can use the object-fit property to solve this. HTML:

<div class="parentDiv"> 
    <video class="cam_video" autoplay></video>                      
</div>

CSS:

.cam_video {
object-fit: fill;
}

This would make the video stretch to occupy the entire parent div.

lightbringer
  • 399
  • 4
  • 19
  • This property unfortunately doesn't work for video in IE or Edge. You can however vote for it to be included in future Edge updates here: https://wpdev.uservoice.com/forums/257854-microsoft-edge-developer/suggestions/32011258-object-fit-and-object-position-for-all-media-eleme – pjk_ok May 22 '18 at 20:22
7

I was just in a similar situation, came to a solution not already mentioned:

html and body filling the viewport, #header and #footer with a content-defined height and #content taking the remaining space in between.

#content already was position: relative for other reasons, so adding position: absolute to the <video> was enough to make it fit snugly.

Now object-fit: contain crops the top and bottom when the viewport's height isn't enough to fit the entire video, just like it does left and right when the viewport is too narrow.

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

body {
  display: flex;
  flex-direction: column;
}

#content {
  height: 100%;
  position: relative; /* magic sauce II */
}

video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  position: absolute; /* magic sauce */
}

/* colors for demonstration */
#header, #footer { background: green; }
video { background: blue; }
<html>
  <body>
    <div id="header">...</div>
    <div id="content">
      <video src="http://www.w3schools.com/html/movie.mp4"></video>
    </div>
    <div id="footer">...</div>
  <body>
</html>
kiw
  • 748
  • 1
  • 9
  • 18
5
 object-fit: cover;

That did the trick for me.

albiesoft.com
  • 71
  • 1
  • 1
  • This property sadly doesn't work for video in IE or Edge. You can however vote for it to be included in Edge here: https://wpdev.uservoice.com/forums/257854-microsoft-edge-developer/suggestions/32011258-object-fit-and-object-position-for-all-media-eleme – pjk_ok May 22 '18 at 20:23
3

My anwser is based on the answers from 4dgaurav and Umair Muhammad Abbas.

Example in jsfiddle

HTML

<div class="wrapper">
  <video class="videoInsert">
  <source src="http://www.w3schools.com/html/movie.mp4" type="video/mp4">
  <source src="movie.ogg" type="video/ogg">
  Your browser does not support the video tag.
 </video>
</div>

CSS


.videoInsert {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: inline-block;
}

.wrapper {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

What seems to work is combination of hidden overflow in the container and inline-block for the video element.

Josha
  • 579
  • 3
  • 7
  • Actually this worked out of everything. Just setting `width` and `height` to 100% on `videoInsert` did the trick. No need for `object-fit` or `display`. – evolross Jun 28 '22 at 19:18
1

Here is the trick which is usedto make video tag draggable and resizable at the same time it is not perfect but you can improve it.

->On the github orignal link( https://github.com/umairabbasDev/draggable-resizable).

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>draggable & resizable</title>
    <link
      href="https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css"
      rel="stylesheet"
    />
    <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
    <script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>

    <!-- CSS -->
    <style>
      .ui-widget-header {
        background: #fffd95;
        color: #0f0f0f;
        font-weight: bold;
      }
      .ui-widget-content {
        background:transparent;
        color: #333333;
      }

      #resizable-3 {
        max-width: 1000px;
        max-height: 800px;
        /* padding: 0.5em; */
        text-align: center;
        margin: 0;
      }

      video {
        width: 100%;
        height: 100%;
        object-fit: cover;
        display: inline-block;
        vertical-align: middle;
      }
    </style>

    <!-- Javascript -->
    <script>
      $(function () {
        $("#content").resizable({
          ghost: true,
        });
        $( "#content" ).draggable();
      });
    </script>
  </head>

  <body>
    <!-- HTML -->
    <div id="content" class="ui-widget-content">
      <video class="ui-widget-header" controls muted autoplay loop>
        <source
          src="https://archive.org/download/WebmVp8Vorbis/webmvp8.webm"
          type="video/webm"
        />
        <source
          src="https://archive.org/download/WebmVp8Vorbis/webmvp8_512kb.mp4"
          type="video/mp4"
        />
        <source
          src="https://archive.org/download/WebmVp8Vorbis/webmvp8.ogv"
          type="video/ogg"
        />
        Your browser doesn't support HTML5 video tag.
      </video>
    </div>
  </body>
</html>
0

Here is my solution, I used a wrapper div . used flex in parent div with flex of each element video element to center and fit them

body,
html,
* {
  padding: 0;
  margin: 0;
}

.wrapper {
  background: #999;
  width: 100%;
  height: 100vh;
  overflow-y: auto;
  overflow-x: hidden;
  display: grid;
  grid-gap: 1rem;
  align-items: center;
  justify-content: center;
  grid-auto-flow: columns;
  grid-template-columns: repeat(auto-fit, minmax(20rem, auto));
  scroll-behavior: smooth;
}

.video1, .video2, .video3, .video4, .video5, .video6, .video7, .video8 {
  box-shadow: 0 10px 10px rgba(0, 0, 0, 0.15);
  border-radius: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.video1 video, .video2 video, .video3 video, .video4 video, .video5 video, .video6 video, .video7 video, .video8 video {
  width: 100%;
  height: 100%;
  object-fit: fill;
  border-radius: inherit;
}
<div class="wrapper">
  <div class="video1">
    <video src="http://www.w3schools.com/html/movie.mp4" controls></video>
  </div>
  <div class="video2">
    <video src="http://www.w3schools.com/html/movie.mp4" controls></video>
  </div>
  <div class="video3">
    <video src="http://www.w3schools.com/html/movie.mp4" controls></video>
  </div>
  <div class="video4">
    <video src="http://www.w3schools.com/html/movie.mp4" controls></video>
  </div>
  <div class="video5">
    <video src="http://www.w3schools.com/html/movie.mp4" controls></video>
  </div>
  <div class="video6">
    <video src="http://www.w3schools.com/html/movie.mp4" controls></video>
  </div>
  <div class="video7">
    <video src="http://www.w3schools.com/html/movie.mp4" controls></video>
  </div>
  <div class="video8">
    <video src="http://www.w3schools.com/html/movie.mp4" controls></video>
  </div>
</div>
Ranjan Kumar
  • 321
  • 3
  • 4
0

You can try to add this is your css:

min-height: 100%;
min-width: 100%;
object-fit: cover;
user3284707
  • 3,033
  • 3
  • 35
  • 69
0

add

object-fit: cover

to your video element, so f.e.:

video {
  object-fit: cover;
}
tdbr
  • 316
  • 1
  • 3
  • 9