Scalable videos with aspect ratio

zzzzBov

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 StackOverflow, 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%;
}