Reputation: 233
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>
?
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.
Upvotes: 0
Views: 1807
Reputation: 14340
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?
Upvotes: 2
Reputation: 19
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).
Upvotes: 0