skip to Main Content

I want to create a responsive <div> that can change its width/height as the window’s width and height changes, while maintaining its aspect ratio and filling the maximum space available in a parent div with no overflow. The parent div is responsive, with height:100vh and width:100vw.

Are there any CSS rules that would allow me to maintain aspect ratio, and expand to fill this <div>?

enter image description here

When the window width > window height:
I want the responsive div to have horizontal aspect-ratio [16/9] (horizontal video) and to take up maximum space in the 100vh parent div without overflow.

When the window width < window height: I want the responsive div to have vertical aspect-ratio [9/16] (vertical video) and to take up maximum space in the 100vh div without overflowing the div.

If there is a pure CSS solution to this, I would be so grateful.

Here is what I’ve tried so far:

.parent {
  background: pink;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.child {
  aspect-ratio: 16/9;
  background: blue;
}

@media (max-aspect-ratio: 9/16) {
  .child {
    aspect-ratio: 9/16;
    height: 100%;
  }
}

@media (min-aspect-ratio: 16/9) {
  .child {
    aspect-ratio: 16/9;
    background: green;
    width: 100%;
  }
}
<div class="parent">
  <video class="child"></video>
</div>

I can’t make the video take up maximum space in the parent without overflow.

Thanks for reading.

2

Answers


  1. If I have understood it properly, you want to rotate the video when it’s in portrait mode to fit a bigger height, which could be solved by a media query:

    yourdiv{
        width:100%; /* to be as big as possible without overflowing */
    }
    yourvideo{
        object-fit:contain; /*To avoid deforming the video*/
    }
        
    @media (orientation: portrait){
        yourdiv{
            transform: rotate(90deg); /*change the video to 9:16 when it's in portrait mode (width < height) */
        }
    }
    

    However, if this isn’t what you’re looking for, try to give more information on what you want to do (f.e. I want to keep the video horizontal but just adapt it to a portrait screen).

    Login or Signup to reply.
  2. Note this answer has been edited in response to the OP’s comment

    This snippet demonstrates the problem. The inner <div> stays within its container when the container is very wide or very tall, but not when the container is squarer.

    .parent {
      border: 2px solid mediumvioletred;
      box-sizing: border-box;
      display: flex;
      justify-content: center;
      align-items: center;
      margin-bottom: 2em;
    }
    
    .wide {
      width: 250px;
      height: 100px;
    }
    
    .less-wide {
      width: 140px;
      height: 100px;
    }
    
    .tall {
      width: 100px;
      height: 250px;
    }
    
    .less-tall {
      width: 100px;
      height: 140px;
    }
    
    .video {
      background: lavenderblush;
      box-sizing: border-box;
    }
    
    .wide .video, .less-wide .video {    /* you would use @media (orientation: landscape) { .video{} } instead */
      height: 100%;
      width: auto;
      aspect-ratio: 16/9;
    }
    
    .tall .video, .less-tall .video {    /* you would use @media (orientation: portrait) { .video{} } instead */
      height: auto;
      width: 100%;
      aspect-ratio: 9/16;
    }
    <div class="parent wide">
      <div class="video"></div>
    </div>
    
    <div class="parent less-wide">
      <div class="video"></div>
    </div>
    
    <div class="parent tall">
      <div class="video"></div>
    </div>
    
    <div class="parent less-tall">
      <div class="video"></div>
    </div>

    If the inside element is a replaced element instead of a <div>, we can use object-fit: contain; and the problem is trivial.

    .parent {
      border: 2px solid mediumvioletred;
      box-sizing: border-box;
      display: flex;
      justify-content: center;
      align-items: center;
      margin-bottom: 2em;
    }
    
    .wide {
      width: 250px;
      height: 100px;
    }
    
    .less-wide {
      width: 140px;
      height: 100px;
    }
    
    .tall {
      width: 100px;
      height: 250px;
    }
    
    .less-tall {
      width: 100px;
      height: 140px;
    }
    
    video {
      background: lavenderblush;
      box-sizing: border-box;
      width: 100%;
      height: 100%;
      object-fit: contain;
    }
    <div class="parent wide">
      <video>
        <source src="https://donald.net.au/bugs/16x9.mp4" type="video/mp4">  
      </video>
    </div>
    
    <div class="parent less-wide">
      <video>
        <source src="https://donald.net.au/bugs/16x9.mp4" type="video/mp4">  
      </video>
    </div>
    
    <div class="parent tall">
      <video>
        <source src="https://donald.net.au/bugs/9x16.mp4" type="video/mp4">  
      </video>
    </div>
    
    <div class="parent less-tall">
      <video>
        <source src="https://donald.net.au/bugs/9x16.mp4" type="video/mp4">  
      </video>
    </div>

    The thing about replaced elements is that they have an intrinsic aspect ratio. It would be nice if the object-fit behaviour could also be used for a non-replaced element with an aspect-ratio specified in CSS, but I don’t believe it can, at least not yet. aspect-ratio is fairly new to CSS, so perhaps this will happen in time.

    But do you really need to make it work with a <div>? Perhaps the solution is to put your video directly inside your parent, rather than having another <div> in-between?

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