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.
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
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.
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%;
}