FitVids.js is still a perfectly workable mini plugin for making videos (or anything) responsive. You need it, or something like it, for sites that have things like YouTube or Vimeo videos, Instagram embeds, or really anything that’s not responsive in the aspect-ratio sense. <img>
/<video>
resize their width/height in an aspect ratio friendly way, <iframe>
/<canvas>
/<object>
do not.
Reframe.js is kind of a modernized version of FitVids.
- It’s bower and npm friendly.
- You can
require
it. - It doesn’t need jQuery.
While they largely do the same thing, there are some slight differences:
- FitVids injects the CSS it needs while Reframe expects you to add it to your stylesheet.
- You call FitVids on a container to search for elements in. You give Reframe selectors directly. You can customize what gets found and filter with either.
When we tweeted it, there were several responses along the lines of:
Why would you use this when you can just use the padding hack?
Indeed, these both use the padding hack, or “intrinsic ratios”. Wrap a container element around the thing, make it height: 0; padding-top: 56.25%; position: relative;
then absolutely position the element within to cover it entirely. But doing it that way means:
- You have to place the wrapper element in your content yourself.
- Everything you embed better be 16:9.
Using either of these libraries means:
- The wrapper gets injected for you.
- What you embed gets measured and the correct aspect ratio applied.
Both are valuable. I don’t wanna hand-write div wrappers on stuff, I just wanna copy and paste embed code. And not all things are 16:9.
I use a selection of common pre-set aspect ratios which has a readable syntax IMO:
Amen to that.
I’m particular to using markdown and a series of post-processors that add various embellishments. Embeds tend to be easy to handle once server-side (example uses cheerio in node):
Certainly this code doesn’t show how to handle different aspect ratios on embeds, but that can be added easily as well.
You can write some classes to handle different aspect ratios for you – I’ve got a pen where the minified CSS would be less than 350 bytes: http://codepen.io/KBD/pen/EVGjYG
If you’re coding something that can end up as a component in a CMS, or you already have a video-player component in a CMS, there’s no need to worry about adding the wrapper each time.
Though this does make me wonder why there isn’t an
aspect-ratio
rule in CSS. Something like:which would calculate the height as 9 units high for every 16 units wide. If you have an explicit width (16rem, for example) it’d be 9rem high.
This will do it. :)
It’s the concept I use to keep slideshows in the same ratio, regardless of screen size.
The reason I prefer not using JavaScript for this sort of thing is that I’m obsessively into progressive enhancement. HTML has base content, CSS loads next with base styling, and finally JavaScript adds whatever it does. If something can be handled earlier in the pipeline (by CSS instead of JS), it should be done that way so that more users can use it. This probably falls under the separation of concerns stuff also.
When JavaScript has to run to make something the correct size, you have two options:
Use render-blocking JavaScript, which slows the page down
Have the page look wrong until JavaScript loads and fixes it
When you handle it with CSS only, you avoid both problems.
To get around calculating the percentages of a padding box by hand, you can use Sass:
When you combine it with BEM, you can quickly create a new video size whenever you need to. Inuit.css has a ratio object that does something like this.
I wrote reframe.js a few days ago & didn’t expect the amount of feedback it got. It’s been very special for me (thanks Chris). Initially, it was written because we weren’t using jQuery on a product I’m working on.
Then I realized with rollup.js & removing a few assumed things I could make the code a bit lighter for my uses.
I appreciate the
intrinsic ratio css mixin
approach discussed above but that didn’t work for my use case.Now, I just received a great question in the reframe.js github repo regarding issues that come up with iframes when they are moved on dom. I wrote another version of the plugin that does not require a div wrapper but it works differently.
Does anyone have any ideas/opinions on the best way to approach this sort of change?
~Thanks
I work on an email templating product and we deal a lot with iframes and dragged iframes and we’ve found the only way around the bugs that reset iframes to default when they are moved in the DOM is to store their state when the drag starts and when it finishes you set their state again.
We have WYSIWYG editors on those iframes so when drag starts the editor details (content and so on) are stored then the editor is destroyed. When the drag finishes the editor is recreated and the content inserted.
I often have to implement responsive video embeds and instead of trying the ‘padding’ hack I’ve taken to just copy/pasting the embed code directly from Youtube or Vimeo with the
width=""
andheight=""
attributes intact, and using JS to calculate the correct height for the element as the width adapts to fill its container responsively: http://codepen.io/tomhodgins/pen/PZqaLmIn another example, the desired aspect ratio is stored in a custom data attribute called
data-ratio=""
and read by (JS and) CSS and the correct height is calculated based on the same formula: http://codepen.io/tomhodgins/pen/XKJpYr