Responsive YouTube or Vimeo embed with Bootstrap or Roots.io in WordPress

By kristoffer,

  Filed under: Code, Wordpress
  Comments: Comments Off on Responsive YouTube or Vimeo embed with Bootstrap or Roots.io in WordPress

I thought I’d share a WordPress filter that I just wrote for this site. I was going to embed a Vimeo video for my up-coming Heading Numbers add-on for Google Docs and needed a nice way to embed it responsively. I am currently running my site on the Roots.io WordPress starter theme. Roots is loaded with Bootstrap front end framework. This blog-post will cover how to responsively embed video and other content into your Bootstrap-powered WordPress. If you just want the code for the responsive embed filter, scroll to the bottom of the post. Now I’ll explain how its done, step by step.

How Bootstrap does responsive video embed

Bootstrap is shipped with a component called Responsive Embed. It is not much code that makes up the component. The following code is from the Bootstrap-sass Repo.

// Embeds responsive
// Credit: Nicolas Gallagher and SUIT CSS.

.embed-responsive {
  position: relative;
  display: block;
  height: 0;
  padding: 0;
  overflow: hidden;

  .embed-responsive-item,
  iframe,
  embed,
  object,
  video {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    height: 100%;
    width: 100%;
    border: 0;
  }

  // Modifier class for 16:9 aspect ratio
  &.embed-responsive-16by9 {
    padding-bottom: 56.25%;
  }

  // Modifier class for 4:3 aspect ratio
  &.embed-responsive-4by3 {
    padding-bottom: 75%;
  }
}

As seen from this code, and the documentation, we need to wrap the embedded item (e.g. iframe in a container that has the class .embed-responsive and add a modifier class based on the aspect ratio. And it turns out that the aspect ratio is just a simple padding to the bottom. So the next thing is to figure out how WordPress handles embeds.

WordPress and embedding video

WordPress is actually pretty awesome when it comes to embedding content. To embed a video, all one has to do is to add the video url in the post/page.

http://www.youtube.com/watch?v=dQw4w9WgXcQ

You can check out the embed documentation to find out which sites are included. The WordPress documentation is however pretty limited as to how one can interact with the embed feature. So – we have to head on over to the WordPress source code. And, there we go, on line 165 of class-wp-embed.php we find the filter hook embed_oembed_html. If you are not familiar with WordPress filters, it think this would be a nice place to start. Anyways, here is the documentation for the filter.

/**
* Filter the cached oEmbed HTML.
*
 * @since 2.9.0
 *
* @see WP_Embed::shortcode()
*
* @param mixed $cache The cached HTML result, stored in post meta.
* @param string $url The attempted embed URL.
* @param array $attr An array of shortcode attributes.
* @param int $post_ID Post ID.
*/
return apply_filters( 'embed_oembed_html', $cache, $url, $attr, $post_ID );

So, what I want to know now is what the values in $attr is. So, I simply set up a test filter that var_dump‘ed the contents of $atts for a Vimeo and a Youtube video. Here’s the sample code.

function var_dump_embed_oembed_html_attr($html, $url, $attr){
 var_dump($attr);
 return $html;
}
add_filter( 'embed_oembed_html','var_dump_embed_oembed_html_attr',10,3); // Need three input parameters

The output is pretty disappointing. First of all, it only contains a width and a height parameter. to begin with, this would be nice to know (for aspect ratio calculations), but it only contains default values from the pretty annoying function wp_embed_defaults. So, it has no use to us. That means we are left with the html and the url.

The WordPress filter

So this is my plan for the filter:

  1. Remove width and height attributes from the html.
  2. Decide what aspect ratio to use
  3. Wrap the embed html in a div with the proper css classes
  4. Return the html

The problem here is number 2 – how to decide on aspect ratio. I’ll leave that for another post (soon, I promise). And then just stick with one aspect ratio. I’ll choose 16by9 for now. And here goes the code:

function bootstrap_wrap_oembed( $html ){
  $html = preg_replace( '/(width|height)="\d*"\s/', "", $html ); // Strip width and height #1
  return'<div class="embed-responsive embed-responsive-16by9">'.$html.'</div>'; // Wrap in div element and return #3 and #4
}
add_filter( 'embed_oembed_html','bootstrap_wrap_oembed',10,1);

And voilá, you have yourself a pretty, responsive, video embed. I’ve borrowed the widht/height remover from Css-tricks.