htmlcssvideocss-gridobject-fit

Why doesn't `width:100%; height:100%; object-fit: contain;` make a <video> fit its container?


So I have a page with a grid layout, with a header and a footer and a black content container in the middle.

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

.container {
  display: grid;
  height: 100%;
  grid-template-rows: max-content 1fr max-content;
}

.container div {
  border: 1px solid red;
}

.videoContainer {
  background-color: black;
}

video {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
<div class="container">
  <div>This is the header</div>
  <div class="videoContainer">
  </div>
  <div>This is the footer</div>
</div>

So far so good.

Now I want to put a video that will stretch to fit this container (and be centered). Here's attempt with object-fit: contain;

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

.container {
  display: grid;
  height: 100%;
  grid-template-rows: max-content 1fr max-content;
}

.container div {
  border: 1px solid red;
}

.videoContainer {
  background-color: black;
}

video {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
<div class="container">
  <div>This is the header</div>
  <div class="videoContainer">
    <video width="400" controls>
      <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
    </video>
  </div>
  <div>This is the footer</div>
</div>

But it doesn't work. Instead of fitting the video to the container, the container expands to fit the video.

How can I keep the container at its inherent dimensions and make the video fit its container?


Solution

  • 1fr

    The first thing you need to know is that 1fr is equivalent to minmax(auto, 1fr), meaning that the container won't be smaller than its content, by default.

    So, start by replacing 1fr with minmax(0, 1fr). That will solve the overflow problem.

    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    .container {
      display: grid;
      height: 100%;
      grid-template-rows: max-content minmax(0, 1fr) max-content;
    }
    
    .container div {
      border: 1px solid red;
    }
    
    .videoContainer {
      background-color: black;
    }
    
    video {
      width: 100%;
      height: 100%;
      object-fit: contain;
    }
    <div class="container">
      <div>This is the header</div>
      <div class="videoContainer">
        <video width="400" controls>
          <source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
        </video>
      </div>
      <div>This is the footer</div>
    </div>


    object-fit

    If you want the video to actually "fit this container" (as in cover the full width and height), then try object-fit: cover as opposed to contain.