Both Bootstrap and Foundation are packaged with responsive video wrappers.

Both work in a similar way. An iframe or video are positioned absolutely inside a relative <div> tag.

The div takes it’s aspect ratio from its bottom padding.

The technique is well established, works well across devices and is dead easy to implement.

How Wordpress [video] shortcode works

By default if you insert media inside the Wordpress WYSIWG editor it will create a shortcode like this

[video width="1920" height="1080" mp4="https://domain.tld/mediapath/file.mp4"][/video]

This creates the following HTML output within the post.

<div style="width: 1920px;" class="wp-video">
	<!--[if lt IE 9]><script>document.createElement('video');</script><![endif]-->
	<video class="wp-video-shortcode" id="video-XXXX-Y" width="1920" height="1080" preload="metadata" controls="controls">
		<source type="video/mp4" src="https://domain.tld/mediapath/file.mp4" />
		<a href="https://domain.tld/mediapath/file.mp4">https://domain.tld/mediapath/file.mp4</a>
	</video>
</div>

This is a bit of a mess.

Not only is the output unresponsive; but because the width is defined on the containing div it will often exceed the width of the page

The Solution

What is preferable is that we create a responsive container that will fit any aspect ratio video on the fly.

To do this we simply need to override the wp_video_shortcode filter; remove the existing div; and wrap the video in a responsive div with the padding defined from the aspect ratio of the video.

I use the following code. This can be inserted directly into a themes function.php file.

/* ========================================================================================================================

Wrap Wordpress Video Shortcode in Responsive Wrapper

======================================================================================================================== */

function lookupIDfromURL($image_url) {

	// basic lookup from DB to match media URL with media URL
	global $wpdb;
	$attachment = $wpdb->get_col($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE guid='%s';", $image_url )); 
        return $attachment[0]; 

}

add_filter( 'wp_video_shortcode', function( $output ) {

	// get SRC 
	// this is a bit hacky

	preg_match( '@src="([^"]+)"@' , $output, $match );
	$src = array_pop($match);
	$src = preg_replace('/\?.*/', '', $src);

	// get ID

	$postid = lookupIDfromURL( $src );
	$meta = wp_get_attachment_metadata($postid);

	// let it autoplay 
	// and include playsinline to fix issues on iOS

	$output = str_replace( "<video", "<video muted playsinline autoplay loop ", $output );
	$output = str_replace( "controls=", "data-controls=", $output );
	
	// wrap it all up

	$str = preg_replace('/\<[\/]{0,1}div[^\>]*\>/i', '', $output);
	$padding = ($meta['height']/$meta['width'])*100;
	$wrap = "<div class='flex-video' style='padding-bottom:".$padding."%'>".$str."</div>";
    
	$output = $wrap;
	return $output;

} );

This will now have Wordpress return a responsive element.

<div class='flex-video' style='padding-bottom:56.25%'>
	<!--[if lt IE 9]><script>document.createElement('video');</script><![endif]-->
	<video muted playsinline autoplay class="wp-video-shortcode" id="video-XXXX-Y" width="1920" height="1080" preload="metadata" data-controls="controls">
		<source type="video/mp4" src="https://domain.tld/mediapath/file.mp4" />
		<a href="https://domain.tld/mediapath/file.mp4">https://domain.tld/mediapath/file.mp4</a>
	</video>
</div>

This will autoplay and loop. It has hidden controls and is muted which allows it to autoplay on mobile devices and Chrome.

This assumes you will treat your video’s like a GIFs. If you do not and want to keep controls comment out the str_replace replace lines.

Responsive Video Class

I am using the flex-video class (which Foundation uses for responsive media elements).

If you using bootstrap replace it with embed-responsive.

If you do not wish to use either framework simply add the following CSS to your design.

.flex-video {
	width:100%;
	height:0px;
	overflow:hidden;
	padding-bottom:56.25%
}
.flex-video iframe,
.flex-video video {
	position:absolute;
	top:0;
	left:0;
	width:100%;
	height:100%;
}