Embedded video in responsive lay-outs

Many videos on the web are hosted at third parties and included through an <iframe>. This can be a problem for flexible width sites, as an <iframe> with 100% width will not automatically have a height that respects the aspect ratio of the embedded content.

Forcing an aspect ratio-respecting height

The embedded content will, it its simplest form, be like:


The width of the video can be adjusted to the width of its container or viewport by setting a width: 100% to the <iframe>, Because the width is not set on the video element itself, as it can be with inline <img> or <video> elements, the browser doesn’t know what the height should be, as there can be any number of elements in your <iframe>.

Let’s wrap the <iframe> in its own container.

<div class="embed-holder">

The embed-holder will be positioned relatively, so that it flows with the page. Its max-width will be 100% and its overflow will be set to hidden. We add a padding-top to the container to reserve some space for the YouTube player.

Now comes the trick1: the embed-holder will get a padding-bottom of 56.25%. Using a percentage for the padding forces a height that is relative to the width of the element. If we want the embed to stick to the aspect ratio of 16:9, we need to express that ratio as 100:x. We can calculate that by dividing 100 by 16, then multiplying the answer with 9.

Let’s for now assume videos in the ratio of 16:9. Using the following CSS, .embed-holder will have the correct aspect ratio in any container or viewport.

.embed-holder {
  max-width: 100%;
  overflow: hidden;
  padding-top: 30px;
  padding-bottom: 56.25%; /* ensuring 16:9 aspect ratio; 
use 75% for a 4:3 ratio */

<p>The last step is to fit the video into the container.</p>

.embed-holder iframe {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;

The .embed-holder acts as the positioning context for the <iframe>. The width and height will be that of .embed-holder, so it will have the correct ratio.

Extra step for WordPress users

If you want to do this in WordPress, one extra step is required.

By default, WordPress creates embeds from any URLs to video services like YouTube and Vimeo. Rightfully, it does not add an extra wrapping element to your code, which is what we need in this particular situation.

To do this, simply add a filter2 to the embedding function in your functions.php :

add_filter('embed_oembed_html', 'wrap_embedded_els', 99, 4);
function wrap_embedded_els($html, $url, $attr, $post_id) {
  return '<div class="embed-holder">' . $html . '</div>';

This wraps the WordPress-generated embeds into a container, to which the above CSS can be applied.

Please note: this wraps all embeds, including some you may not want to apply a different aspect ratio to, such as SoundCloud.


1 This is not my own idea, it has been explained by others. Original idea by Thierry Koblentz on A List Apart (May 2009)

2 Function via cubecolour , who also made a WordPress plugin to add both the CSS and the filter)

Comments, likes & shares

No webmentions about this post yet! (Or I've broken my implementation)