CSS & HTML video tutorial: Managing an aspect ratio in CSS
When integrating videos (via iframe or the video tag) we often want the element to respect a predefined ratio whatever the width of the element. We will see the different methods that can be used to solve this problem.
CSS property aspect-ratio
The property aspect-ratio
is still in the draft stage and is little supported, but it offers a simple solution.
.video {
aspect-ratio: 16/9;
width: 100%;
height: auto;
}
Thus, the element will automatically take a height according to the defined ratio. However, it is important to note that the ratio can be overridden if you force a certain height.
For example a max-height
will outweigh the ratio:
.video {
aspect-ratio: 16/9;
width: 100%;
height: auto;
max-height: 350px;
}
Also, if the content exceeds in height, the height of the element will be adapted to avoid overflow.
The padding-bottom
in %
While waiting for property support aspect-ratio
alternative methods can be used to achieve a similar result. An interesting property of the padding is that if the unit is in percentage the calculation is done in relation to the width of the container.
percentage: The size of the padding as a percentage, relative to the width of the containing block. Must be negative.
We can therefore use this specificity to obtain a height based on the width.
.ratio {
position: relative;
}
.ratio :: before {
happy:'';
display: block;
/ * ratio of 16/9 * /
padding-bottom: 56.25%;
}
.ratio> * {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
We can also use CSS variables to make things dynamic
.ratio :: before {
padding-bottom: calc (100% / (var (- ratio, calc (16/9))));
}
This makes it possible to control the ratio via a simple property.
The downside to this approach is that it is not possible to push the height of the element if the content is overflowing.
display grid
This technique can be improved by replacing the absolute position system with a 1 by 1 grid.
.ratio {
position: relative;
display: grid;
}
.ratio :: before {
happy:'';
padding-bottom: calc (100% / (var (- ratio, calc (16/9))));
grid-area: 1/1;
}
.ratio> * {
width: 100%;
height: 100%;
grid-area: 1/1;
}
/ * To prevent images / iframe from pushing content, we use the previous approach * /
.ratio> img,
.ratio> iframe {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
Thanks to this approach we get the overflow behavior if the element's child protrudes.
SVG to manage the ratio
The downside of padding-bottom
is that it is not possible to limit its height via a max-height
or one min-height
. It is possible to replace the pseudo element by an SVG to force the ratio.
Hi world
We give the SVG a viewbox to force a specific ratio (here 16 / 9th). We will then give it a width of 100% in CSS and the height will be calculated automatically by the browser.
.ratio {
position: relative;
display: grid;
}
/ * The SVG will enforce the ratio * /
.ratio> svg {
width: 100%;
height: auto;
/ * We can force a max height or a min max-height: 200px; * /
}
.ratio> * {
grid-area: 1/1;
}
/ * To prevent images / iframe from pushing content, we use the absolute approach * /
.ratio> img,
.ratio> iframe {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
If you do not want to "pollute" your HTML structure with an empty element, it is also possible to use SVG directly via the property happy
.
.ratio {
position: relative;
display: grid;
}
.ratio :: before {
content: url ("data: image / svg + xml,% 3Csvg xmlns = 'http: //www.w3.org/2000/svg' viewBox = '0 0 16 9'% 3E% 3C / svg% 3E") ;
width: 100%;
height: auto;
grid-area: 1/1;
}
.ratio> * {
grid-area: 1/1;
}
/ * To prevent images / iframe from pushing content, we use the absolute approach * /
.ratio> img,
.ratio> iframe {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
This solution is in my opinion the most complete
- We can force a height via a
min-height
or onemax-height
on SVG - Content can spill over and make the box grow.
On the other hand, it is not possible to use a CSS variable to be able to control the ratio (in this case there we can return to the SVG method in the HTML code).