Search code examples
htmlcssgridviewport

How to lock a 3x3 grid to the viewport regardless of content size?


I'm trying to create a page for CCTV camera streams that displays 9 streams in a 3x3 grid, using the full available width and height, without scrolling. The streams are different resolutions but I want the grid to resize the videos (ignoring aspect ratio, the video player handles this) so every video is visible.

I have this so far but I can't get the grid to resize the video elements so everything stays in the viewport.

body {
  margin: 0;
}

#container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  height: 100vh;
}

.item {
  border: 2px solid red;
  background-color: blue;
}

.item video {
  width: 100%;
  height: 100%;
}
<div id="container">
  <div class="item">
    <video src="https://placehold.co/600x500.mp4" />
  </div>
  <div class="item">
    <video src="https://placehold.co/600x400.mp4" />
  </div>
  <div class="item">
    <video src="https://placehold.co/600x400.mp4" />
  </div>
  <div class="item">
    <video src="https://placehold.co/600x400.mp4" />
  </div>
  <div class="item">
    <video src="https://placehold.co/600x400.mp4" />
  </div>
  <div class="item">
    <video src="https://placehold.co/600x400.mp4" />
  </div>
  <div class="item">
    <video src="https://placehold.co/600x400.mp4" />
  </div>
  <div class="item">
    <video src="https://placehold.co/600x400.mp4" />
  </div>
  <div class="item">
    <video src="https://placehold.co/600x400.mp4" />
  </div>
</div>


Solution

  • To ensure the 9 cells take up exactly the viewport all elements have had box sizing defined, so borders are within their dimensions, all margins have been set to 0, and the videos are positioned absolute within their cells and given object-fit contain so it is certain the whole video will be seen without stretching.

    If you want instead the videos to fill their cells then use cover instead, but of course they will probably get cropped.

    * {
      margin: 0;
      box-sizing: border-box;
    }
    
    #container {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(3, 1fr);
      height: 100vh;
    }
    
    .item {
      border: 2px solid red;
      background-color: blue;
      position: relative;
    }
    
    .item video {
      width: 100%;
      height: 100%;
      object-fit: contain;
      position: absolute;
    }
    <div id="container">
      <div class="item">
        <video src="https://placehold.co/600x500.mp4" />
      </div>
      <div class="item">
        <video src="https://placehold.co/600x400.mp4" />
      </div>
      <div class="item">
        <video src="https://placehold.co/600x400.mp4" />
      </div>
      <div class="item">
        <video src="https://placehold.co/600x400.mp4" />
      </div>
      <div class="item">
        <video src="https://placehold.co/600x400.mp4" />
      </div>
      <div class="item">
        <video src="https://placehold.co/600x400.mp4" />
      </div>
      <div class="item">
        <video src="https://placehold.co/600x400.mp4" />
      </div>
      <div class="item">
        <video src="https://placehold.co/600x400.mp4" />
      </div>
      <div class="item">
        <video src="https://placehold.co/600x400.mp4" />
      </div>
    </div>