<main>
<h1>YouTube embed poster frame widget</h1>
<!-- the class "videoWrapper169" means a 16:9 aspect ration video. Another option is "videoWrapper43" for 4:3. -->
<div class="videoWrapper videoWrapper169 js-videoWrapper">
<!-- YouTube iframe. -->
<!-- note the iframe src is empty by default, the url is in the data-src="" argument -->
<!-- also note the arguments on the url, to autoplay video, remove youtube adverts/dodgy links to other videos, and set the interface language -->
<iframe class="videoIframe js-videoIframe" src="" frameborder="0" allowTransparency="true" allowfullscreen data-src="https://www.youtube.com/embed/hgzzLIa-93c?autoplay=1& modestbranding=1&rel=0&hl=sv"></iframe>
<!-- the poster frame - in the form of a button to make it keyboard accessible -->
<button class="videoPoster js-videoPoster" style="background-image:url(http://i2.wp.com/www.cgmeetup.net/home/wp-content/uploads/2015/05/Avengers-Age-of-Ultron-UI-Reel-1.jpg);">Play video</button>
</div>
<button onclick="videoStop()">external close button</button>
<p>A widget to allow smooth transition between poster frame, YouTube video and back.</p>
<ul>
<li>Expands to fit any container with correct aspect ratio (16:9 and 4:3 variations).</li>
<li>Fully responsive on small screens.</li>
<li>Not using the Youtube js API (only because it's another http call and we'd use barely any of it)</li>
<li>Smooth transition between poster and video</li>
<li>Poster frame doesn't need any "play button" images embedded in, they're CSS elements that part of the widget, so are retina res, easily coloured and have a hover state transition.</li>
<li>videoStop() script, useful for buttons or javascript events (eg closing modals), that removes the src of the youtube video, preventing it from playing after it's hidden. Can be targeted at a particular video, or all on the page.</li>
<li>Delegated click event, allowing the video element to be ajaxed in after page initilisation, and still work.</li>
<li>Keyboard accessible (and a focus state to show when you've correctly selected it)</li>
</ul>
</main>
$color-button: #fff;
$color-button-hover: #f00;
.videoWrapper {
position: relative;
width: 100%;
height: 0;
background-color: #000;
&43 {
padding-top: 75%;
}
&169 {
padding-top: 56%;
}
}
.videoIframe {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
}
.videoPoster {
position: absolute;
top: 0;
right: 0;
left: 0;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
cursor: pointer;
border: 0;
outline: none;
background-position: 50% 50%;
background-size: 100% 100%;
background-size: cover;
text-indent: -999em;
overflow: hidden;
opacity: 1;
-webkit-transition: opacity 800ms, height 0s;
-moz-transition: opacity 800ms, height 0s;
transition: opacity 800ms, height 0s;
-webkit-transition-delay: 0s, 0s;
-moz-transition-delay: 0s, 0s;
transition-delay: 0s, 0s;
&:before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 80px;
height: 80px;
margin: -40px 0 0 -40px;
border: 5px solid $color-button;
border-radius: 100%;
-webkit-transition: border-color 300ms;
-moz-transition: border-color 300ms;
transition: border-color 300ms;
}
&:after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
margin: -20px 0 0 -10px;
border-left: 40px solid $color-button;
border-top: 25px solid transparent;
border-bottom: 25px solid transparent;
-webkit-transition: border-color 300ms;
-moz-transition: border-color 300ms;
transition: border-color 300ms;
}
&:hover,
&:focus {
&:before {
border-color: $color-button-hover;
}
&:after {
border-left-color: $color-button-hover;
}
}
.videoWrapperActive & {
opacity: 0;
height: 0;
-webkit-transition-delay: 0s, 800ms;
-moz-transition-delay: 0s, 800ms;
transition-delay: 0s, 800ms;
}
}
// MISC STUFF FOR THIS EXAMPLE
body {
font-family: avenir,sans-serif;
}
main {
max-width: 800px;
margin: 20px auto;
}
// poster frame click event
$(document).on('click','.js-videoPoster',function(ev) {
ev.preventDefault();
var $poster = $(this);
var $wrapper = $poster.closest('.js-videoWrapper');
videoPlay($wrapper);
});
// play the targeted video (and hide the poster frame)
function videoPlay($wrapper) {
var $iframe = $wrapper.find('.js-videoIframe');
var src = $iframe.data('src');
// hide poster
$wrapper.addClass('videoWrapperActive');
// add iframe src in, starting the video
$iframe.attr('src',src);
}
// stop the targeted/all videos (and re-instate the poster frames)
function videoStop($wrapper) {
// if we're stopping all videos on page
if (!$wrapper) {
var $wrapper = $('.js-videoWrapper');
var $iframe = $('.js-videoIframe');
// if we're stopping a particular video
} else {
var $iframe = $wrapper.find('.js-videoIframe');
}
// reveal poster
$wrapper.removeClass('videoWrapperActive');
// remove youtube link, stopping the video from playing in the background
$iframe.attr('src','');
}
Also see: Tab Triggers