skip to Main Content

I have a container with a variable amount of videos and I want to keep these videos centered in a container with a maximum of 3 videos per row, up to 9 videos (I split them up into pages with JavaScript but the issue is per page) while maintaining an aspect ratio of 16 / 9.

The container that the videos are in is not full screen height. My issue is that the videos exceed the height of the container. Is there a way to keep the videos within the container while maintaining their aspect ratio and keeping 3 per row without setting a height? The width of the videos doesn’t matter as long as they all fit within the container.

I’ve attached a minimal example below to illustrate the issue. I recommend viewing it full screen to more easily see the issue.

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

.page {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  align-content: center;
  width: 100%;
  height: 100%;
  background-color: #f0f0f0;
}

.container {
  height: calc(100% - 12rem);
  display: flex;
  align-items: center;
  justify-content: center;
  align-content: center;
  flex-wrap: wrap;
  row-gap: 12px;
  column-gap: 12px;
  width: 100%;
  background-color: #444;
}

.video {
  position: relative;
  aspect-ratio: 16 / 9;
  flex-basis: 25%;
  background-color: gray;
}
<div class="page">
  <div class="container">
      <div class="video"></div>
      <div class="video"></div>
      <div class="video"></div>
      <div class="video"></div>
      <div class="video"></div>
      <div class="video"></div>
      <div class="video"></div>
      <div class="video"></div>
      <div class="video"></div>
  </div>
</div>

2

Answers


  1. Maybe use min-width & min-height instead using width and height.

    .page {
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
      align-content: center;
      min-width: 100%;
      min-height: 100%;
      background-color: #f0f0f0;
    }
    

    It will looks like this:

    how it will looks like

    Login or Signup to reply.
  2. The problem arises from the fact that the height of flex containers cannot be defined in CSS. By setting the flex-basis to 25%, we can make a flex child (.item) take up 1/3 of the container’s width.

    Solution #1: sub-child

    However, this causes the element to overflow the container if it tries to maintain the 16/9 aspect ratio. To overcome this, a child element (.item > .video) is needed, which will be the actual video.

    We also set the aspect ratio for this element, take the height as 100% (since the flex child already has a known height of 100%), and center it (I marked it with green).

    html, body {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
    }
    
    .page {
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
      align-content: center;
      width: 100%;
      height: 100%;
      background-color: #f0f0f0;
    }
    
    .container {
      height: calc(100% - 12rem);
      display: flex;
      align-items: center;
      justify-content: center;
      align-content: center;
      flex-wrap: wrap;
      row-gap: 12px;
      column-gap: 12px;
      width: 100%;
      background-color: #444;
    }
    
    /* Container Child */
    .item {
      flex-basis: 25%;
      max-height: calc((100% - 2 * 12px) / 3);
      aspect-ratio: 16 / 9;
      background-color: gray;
    }
    
    /* Really video element (sub-child) */
    .video {
      max-height: 100%;
      aspect-ratio: 16 / 9;
      background-color: green;
      margin: 0 auto;
    }
    <div class="page">
      <div class="container">
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
      </div>
    </div>

    Green element is your 16/9 video element
    Green element without gray bacgkround

    The appearance can be further improved by aligning the videos in the left column to the right instead of the center. The videos in the right column can be aligned to the left. This way, it will appear as if there is a 12px gap between the videos. The gap between the columns will still be slightly larger due to the middle video, but it’s almost correct now.

    html, body {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
    }
    
    .page {
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
      align-content: center;
      width: 100%;
      height: 100%;
      background-color: #f0f0f0;
    }
    
    .container {
      height: calc(100% - 12rem);
      display: flex;
      align-items: center;
      justify-content: center;
      align-content: center;
      flex-wrap: wrap;
      row-gap: 12px;
      column-gap: 12px;
      width: 100%;
      background-color: #444;
    }
    
    /* Container Child */
    .item {
      flex-basis: 25%;
      max-height: calc((100% - 2 * 12px) / 3);
      aspect-ratio: 16 / 9;
      background-color: gray;
    }
    
    /* Really video element (sub-child) */
    .video {
      max-height: 100%;
      aspect-ratio: 16 / 9;
      background-color: green;
    }
    
    /* Left column: Align video to the right (1., 4., 7.) */
    .container .item:nth-child(3n + 1) .video {
      margin-left: auto;
    }
    
    /* Center column: Align video to the center (2., 5., 8.) */
    .container .item:nth-child(3n - 1) .video {
      margin: 0 auto;
    }
    
    /* Right column: Align video to the left (3., 6., 9.) */
    .container .item:nth-child(3n + 2) .video {
      margin-right: auto;
    }
    <div class="page">
      <div class="container">
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
          <div class="item">
             <div class="video"></div>
          </div>
      </div>
    </div>

    Better aligned green videos
    Better aligned green videos without gray bg

    Solution #2: aspect-ratio to container

    You have the option to adjust the size of the flex container to the correct aspect-ratio, so that the three items displayed with a flex-basis: 25% will have a perfect ratio.

    Of course, in this case, you might need an extra element to set the background to 100% width, if necessary.

    html, body {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
    }
    
    .page {
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
      align-content: center;
      width: 100%;
      height: 100%;
      background-color: #f0f0f0;
    }
    
    .container {
      height: calc(100% - 12rem);
      display: flex;
      align-items: center;
      justify-content: center;
      align-content: center;
      flex-wrap: wrap;
      row-gap: 12px;
      column-gap: 12px;
      /* width: 100%; */
      aspect-ratio: 16 / 9; /* instead of width */
      background-color: #444;
    }
    
    .video {
      flex-basis: 25%;
      aspect-ratio: 16 / 9;
      background-color: gray;
    }
    <div class="page">
      <div class="container">
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
      </div>
    </div>

    Solution #2 with a smaller container width

    You can achieve a better result: 0px gap + 6px border for the video elements

    html, body {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
    }
    
    .page {
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: center;
      align-content: center;
      width: 100%;
      height: 100%;
      background-color: #f0f0f0;
    }
    
    .container {
      height: calc(100% - 12rem);
      display: flex;
      align-items: center;
      justify-content: center;
      align-content: center;
      flex-wrap: wrap;
      /* padding: 6px; */ /* And 6px padding for the container to maintain a 12px distance at the edges; but this will increase the container's height */
      /* width: 100%; */
      aspect-ratio: 16 / 9; /* instead of width */
      background-color: #444;
    }
    
    .video {
      flex-basis: calc(100% / 3);
      aspect-ratio: 16 / 9;
      
      /* instead of gap, can use border with border-box */
      border: solid #444 6px;
      box-sizing: border-box;
      
      background-color: gray;
    }
    <div class="page">
      <div class="container">
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
          <div class="video"></div>
      </div>
    </div>

    Better container width + border instead of gap

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search