I'm trying to maximize the size of an element (embedded video player iframe) within particular constraints:
- it should not be taller than 2/3 the height of its parent.
- it should not be wider than its parent.
- it should maintain its 16:9 aspect ratio
I'm currently achieving this with Javascript (0.5625
and 1.778
are decimal representations of the 16:9 aspect ratio):
function updateDimensions () {
const video = document.querySelector('#video-player')
const parentRect = document.querySelector("#parent").getBoundingClientRect()
const maxHeight = parentRect.height * 0.667
const maxWidth = Math.min(maxHeight * 1.778, parentRect.width)
video.setAttribute('width', maxWidth 'px')
video.setAttribute('height', maxWidth * 0.5625 'px')
}
This code is run once on mount, and (debounced) on every resize.
It really seems like this should be CSS' job though, it would probably be more efficient as CSS, and feels like something that should be achievable with calc()
, min()
, custom properties (variables) and aspect-ratio
in CSS, but I just can't work out how.
This is how far I got:
#video-player {
--parent-height: ???
/* 1. should not be higher than 2/3 of its parent */
--max-video-height: calc(var(--parent-height) * 0.667)
/* 2. should not be wider than its parent */
--video-width: min(calc(var(--max-video-height) * 1.778), 100%)
width: var(--video-width)
/* 3. should maintain its 16:9 aspect ratio */
/* height can be calculated with either: */
height: calc(var(--video-width) * 0.5625)
/* or: */
aspect-ratio: 16 / 9
}
The way that I've written it, it all hinges on getting the parent height into a variable.
Is there a way to do so? Or is there another way to write this in CSS to achieve what the Javascript code does?
NOTE: I had previously been using a wrapper div and the #video-container { padding-top: 56.25% }
hack to maintain the video's aspect ratio, but having the container set to position: relative
seemed to conflict with my attempts to align it with align-self: center; justify-self: center;
(it's a grid item). I guess I could wrap the wrapper in another wrapper and put that in the grid, but the Javascript code does exactly what I want to the element in question, without the need for extra divs.
CodePudding user response:
Depending on how your video is being added (<iframe>
or <video>
), this should be all you need:
#video-player { height: 100%; max-height: 66.6667%; aspect-ratio: 16/9; }
Working sample on codepen
Also worth being aware of how well supported aspect-ratio
is. You can see that here on the caniuse website.