Scalable videos with aspect ratio
Earlier today I found a question that had been bugging me for some time. How do you preserve an element's aspect ratio when it's scaled? I hadn't yet found the answer, so I did some quick googling, and quickly found out about a simple trick to preserve aspect ratio with only CSS and a bit of extra markup.
After writing up a quick answer to the question and creating a simple CodePen to demo the trick, I realized that the dummy element was being unnecessarily added. Of course, if I'd seen the duplicate question on Stack Overflow, I could have saved myself a bit of time in writing up a second demo.
My goal was to figure out the minimal markup needed to style a YouTube video such that it'd scale while maintaining aspect ratio. I decided that the <iframe>
could be the inner element, and that all I'd need would be a wrapping <div>
with a class.
CodePen was having issues with YouTube videos at the time, so I quickly made a Fiddle. I was happy with the Fiddle, and didn't have time to update my blog immediately, so I left it for a while.
When I finally got around to updating my blog with the new feature, I decided that I'd like to have a means to specify different aspect ratios. I could set up multiple aspect-ratio classes, but I decided that this would be far too verbose, and what I really wanted was a minimalistic approach. Instead of using a wrapper class of .youtube
I figured it'd be a bit more portable if I just tied the style to the concept of preserving aspect ratio.
In the interest of not needing to write additional markup, I decided to go with adding a custom [data-aspect-ratio]
attribute to the wrapper <div>
. This way I could specify the desired aspect ratio as the value of the attribute, and I wouldn't need to add duplicate information via the [class]
attribute. class="aspect-ratio aspect-ratio-4-3"
was simply too much to type.
This turned the markup into:
<div data-aspect-ratio="16:9"><iframe ...></iframe></div>
Not bad. Using a [data-*]
attribute also gave the the flexibility to define a wide variety of aspect ratios, without the need for high-specificity selectors. In the end, my LESS became:
[data-aspect-ratio] {
display: block;
max-width: 100%;
position: relative;
&:before {
content: '';
display: block;
}
> * {
display: block;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
}
[data-aspect-ratio="3:1"]:before {
padding-top: 33.33%;
}
[data-aspect-ratio="2:1"]:before {
padding-top: 50%;
}
[data-aspect-ratio="16:9"]:before {
padding-top: 56.25%;
}
[data-aspect-ratio="3:2"]:before {
padding-top: 66.66%;
}
[data-aspect-ratio="4:3"]:before {
padding-top: 75%;
}
[data-aspect-ratio="1:1"]:before {
padding-top: 100%;
}
[data-aspect-ratio="3:4"]:before {
padding-top: 133.33%;
}
[data-aspect-ratio="2:3"]:before {
padding-top: 150%;
}
[data-aspect-ratio="9:16"]:before {
padding-top: 177.77%;
}
[data-aspect-ratio="1:2"]:before {
padding-top: 200%;
}
[data-aspect-ratio="1:3"]:before {
padding-top: 300%;
}