Responsive YouTube oEmbeds in WordPress

oEmbeds are an extremely easy way to include video and other media from specific sites on your  WordPress powered site. You only have to paste in the url instead of copy and pasting a large code snippet into the WordPress content editor.

For example, before oEmbeds you would have to copy and paste something like this:

<iframe width="560" height="315" src="https://www.youtube.com/embed/OIEGEjjlMzE" frameborder="0" allowfullscreen></iframe>

and now all you need is this:

https://www.youtube.com/embed/OIEGEjjlMzE

oEmbeds sound perfect, right? Well, it’s almost perfect. WordPress automatically wraps that YouTube link in an iframe with a set width and height. Not a huge deal if you are using a fixed width site, but chances are your site is responsive.

Responsive sites do not get along with elements set with fixed widths and heights. The video embed will overflow the viewport and hang off into the margin. Users will be able to horizontally scroll on the mobile view of your site and that’s not an ideal experience.

However, there is a pretty quick fix for this problem. You only need to add a few lines of CSS and jQuery to your site to make sure that your YouTube oEmbeds will perfectly fit any screen resolution.

1. Set up the jQuery

Copy and paste the following code into a new .js file named ‘responsive-video.js’ inside your theme folder:

jQuery(document).ready(function($) {

	var $all_oembed_videos = $("iframe[src*='youtube']");
	
	$all_oembed_videos.each(function() {
	
		$(this).removeAttr('height').removeAttr('width').wrap( "<div class='embed-container'></div>" );
 	
 	});

});

The next step is to include the javascript file you just created into the front facing part of your site. In your theme’s functions.php file include the following snippet:

function responsive_video() {

     wp_register_script('responsive_video_js',
          get_template_directory_uri() . '/responsive-video.js',
          array('jquery'),
          '1.0' );

     // enqueue the script
          wp_enqueue_script('responsive_video_js');
}

add_action('wp_enqueue_scripts', 'responsive_video');

Please note: If you are using a child theme, swap out get_template_directory_uri() with get_stylesheet_directory_uri().

 2. Add in the CSS

This CSS comes from the site Embed Responsively and it’s amazing! In your style.css file in the root folder of your theme, copy and paste the following snippet:

.embed-container { 
	position: relative; 
	padding-bottom: 56.25%;
	height: 0;
	overflow: hidden;
	max-width: 100%;
	height: auto;
} 

.embed-container iframe,
.embed-container object,
.embed-container embed { 
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}

3. Boom Bam! All done!

Feel free to resize the screen and check out that responsive goodness in the example below:

You should be good to go! Please note that this can be done for other oEmbed services besides YouTube. For example, say you need responsive Vimeo video embeds, then modify your .js file to this:

jQuery(document).ready(function($) {

	var $all_oembed_videos = $("iframe[src*='youtube'], iframe[src*='vimeo']");
	
	$all_oembed_videos.each(function() {
	
		$(this).removeAttr('height').removeAttr('width').wrap( "<div class='embed-container'></div>" );
 	
 	});

});

The inspiration for this tutorial came from a mash up of these CSS Tricks and Embed Responsively articles.

14 thoughts to “Responsive YouTube oEmbeds in WordPress”

  1. Even simpler, no need for jQuery or php.

    iframe {
    width: 350px; // optional default width
    max-width: 100%;
    height: auto;
    }

    If you want a starting width smaller than the container, then either include a width in the css, or put it right in your oembed line:

    wp_oembed_get($video, array(“width”=>350));

    That’s all that is needed.

  2. Hi! I’ve got this working, but I am looking for a way to add in YouTube embed customizations, such as “showinfo=0”, “rel=0”, “hd=1”, allowFullscreen, etc. I haven’t been able to find an answer; any suggestions?

  3. This can be easily done without jQuery on the server side. Just put this anywhere in your functions.php file:

    // responsive oEmbed videos
    add_filter( ’embed_oembed_html’, ‘custom_oembed_filter’, 10, 4 ) ;
    function custom_oembed_filter($html, $url, $attr, $post_ID) {
    $return = ”.$html.”;
    return $return;
    }

    And this css:

    .video-container {
    position: relative;
    padding-bottom: 56.25%; /* 16:9 */
    padding-top: 25px;
    height: 0;
    margin-bottom: 1em;
    width: 100%;
    }
    .video-container iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    }

    It does exactly the same as the jQuery method mentioned here, but the html wrapper is already inserted by a wordpress hook on the oembed function, instead of doing it afterwards in the browser of the client. It’s a bit more ‘clean’.

    Cheers!

    1. Matiyin, not seeing how .video-container is being wrapped around the iframe on the oEmbed. Added your code to functions.php exactly and all it does is add “.” periods around the iframe. Any ideas? Would rather not use jQuery.

    2. This isnt a full solution and isnt valid.
      The proper way to do this without jQuery is the following: (Tested and working with WP 4.9.4)


      function responsive_oembed_filter($html, $url, $args) {

      $wmatches = array(); $hmatches = array();
      $wid = 16;
      $hgt = 9;
      //Find Width and Height variables
      if (preg_match('/width=\"(\d+)\"/i', $html, $wmatches) && preg_match('/height=\"(\d+)\"/i', $html, $hmatches))
      {
      //and store them
      $wid = $wmatches[1];
      $hgt = $hmatches[1];

      //Remove them from the original html string.
      $html = preg_replace('/width=\"(\d+)\"/i', '', $html);
      $html = preg_replace('/height=\"(\d+)\"/i', '', $html);
      }
      //Wrap the html in the container and also calculate the aspect ratio from the width and height and override the CSS in case it's different.
      return ''.$html.'';
      }
      add_filter('oembed_result', 'responsive_oembed_filter', 10, 4);

      You’ll also need the CSS from above:
      .embed-container {
      position: relative;
      padding-bottom: 56.25%; /* 16:9 */
      padding-top: 25px;
      height: 0;
      margin-bottom: 1em;
      width: 100%;
      }
      .embed-container iframe,
      .embed-container embed,
      .embed-container object
      {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      }

      1. Arg, comment section removed all the html…
        That last line should be:

        return ‘> div class=”embed-container” style=”padding-bottom:’.(($hgt/$wid)*100).’%” < ‘.$html.’ > /div <‘;

        1. *EDIT*:
          Arg, comment section removed all the html…
          That last line should be:


          return '<div class="embed-container" style="padding-bottom:'.(($hgt/$wid)*100).'%">'.$html.'</div>';

Leave a Reply

Your email address will not be published. Required fields are marked *