Skip to content

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%;