public
Last active

My current setup for embedding YouTube videos in Jekyll. Responsive layout, poster image first/click to load for faster page loads. Provides a `{% youtube VIDEOID 800 600 "optional caption" %}` tag that generates the markup needed for the CSS and jQuery script.

  • Download Gist
a_lazy_youtube_tag.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
# Title: Responsive Lazy Load YouTube embed tag for Jekyll
# Author: Brett Terpstra <http://brettterpstra.com>
# Description: Output a styled element for onClick replacement with responsive layout
#
# Syntax {% youtube video_id [width height] ["Caption"] %}
#
# Example:
# {% youtube B4g4zTF5lDo 480 360 %}
# {% youtube http://youtu.be/2NI27q3xNyI %}
 
module Jekyll
class YouTubeTag < Liquid::Tag
@videoid = nil
@width = ''
@height = ''
 
def initialize(tag_name, markup, tokens)
if markup =~ /(?:(?:https?:\/\/)?(?:www.youtube.com\/(?:embed\/|watch\?v=)|youtu.be\/)?(\S+)(?:\?rel=\d)?)(?:\s+(\d+)\s(\d+))?(?:\s+"(.*?)")?/i
@videoid = $1
@width = $2 || "480"
@height = $3 || "360"
@caption = $4 ? "<figcaption>#{$4}</figcaption>" : ""
end
super
end
 
def render(context)
ouptut = super
if @videoid
# Thanks to Andrew Clark for the inline CSS calculation idea <http://contentioninvain.com/2013/02/13/video-embeds-for-responsive-designs/>
intrinsic = ((@height.to_f / @width.to_f) * 100)
padding_bottom = ("%.2f" % intrinsic).to_s + "%"
video = %Q{<a class="youtube" href="http://www.youtube.com/watch?v=#{@videoid}" data-videoid="#{@videoid}" data-width="#{@width}" data-height="#{@height}">YouTube Video</a>}
%Q{<figure class="bt-video-container" style="padding-bottom:#{padding_bottom}">#{video}#{@caption}</figure>}
else
"Error processing input, expected syntax: {% youtube video_id [width height] %}"
end
end
end
end
 
Liquid::Template.register_tag('youtube', Jekyll::YouTubeTag)
jquery.lazyyoutube.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
var youTube = (function() {
'use strict';
 
var youTube = {
init: function() {
$(".bt-video-container a.youtube").each(function(index) {
var $this = $(this);
 
var youtubeId = $this.data("videoid");
$this.html(''); // empty any placeholders
$this.prepend('<div class="bt-video-container-div"></div>&nbsp;');
$this.css("background", "#000 url(http://i2.ytimg.com/vi/"+youtubeId+"/0.jpg) center center no-repeat"); // Use poster image from YT as background
var embedUrl = '//www.youtube-nocookie.com/embed/'+youtubeId+'?autoplay=1&rel=0'; // create an embed url.
// no protocol
// youtube-nocookie: prevent additional user tracking
// autoplay: because user already clicked
// rel=0: no "Related Videos" at end
// set up the embed iframe
var videoFrame = '<iframe width="'+parseInt($this.data("width"),10)+'" height="'+parseInt($this.data("height"),10)+'" style="vertical-align:top;" src="'+embedUrl+'" frameborder="0" allowfullscreen></iframe>';
 
$this.click(function(ev){ // replace link with iframe on click
ev.preventDefault();
$this.replaceWith(videoFrame);
return false;
});
});
}
}
 
return youTube;
 
})();
 
// init at an opportune time
youTube.init();
lazyyoutube.css
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
.bt-video-container {
margin-bottom: 3.5em;
display: block;
position: relative;
height: 0; }
.bt-video-container a {
background: #ccc;
position: absolute;
color: #666;
display: block;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-size: cover!important;
text-decoration: none;
text-align: center;
padding-top: 25%; }
.bt-video-container a:hover {
text-decoration: none;
color: #FFF; }
.bt-video-container figcaption {
position: absolute;
left: 0;
bottom: -50px;
display: block;
width: 100%;
box-sizing: border-box;
text-align: center; }
 
.bt-video-container-div {
background: url(/images/youtube-play-button.png) center center no-repeat;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=85);
opacity: 0.85;
-webkit-transition: opacity 0.2s ease-in-out;
-moz-transition: opacity 0.2s ease-in-out;
-o-transition: opacity 0.2s ease-in-out;
-ms-transition: opacity 0.2s ease-in-out;
transition: opacity 0.2s ease-in-out;
position: absolute;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%; }
 
.bt-video-container-div:hover {
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
opacity: 1; }
 
.bt-video-container iframe,
.bt-video-container object,
.bt-video-container embed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
margin-top: 0; }
lazyyoutube.scss
SCSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
.bt-video-container {
margin-bottom: 3.5em;
display:block;
position:relative;
height:0;
a {
background: #ccc;
position: absolute;
color: #666;
display: block;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-size: cover!important;
text-decoration: none;
&:hover {
text-decoration:none;
color:#FFF;
}
text-align: center;
padding-top: 25%;
}
figcaption {
position: absolute;
left: 0;
bottom: -50px;
display: block;
width: 100%;
box-sizing: border-box;
text-align: center;
}
iframe, object, embed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
margin-top: 0;
}
}
 
.bt-video-container-div {
background: url(/images/youtube-play-button.png) center center no-repeat;
@include opacity(.85);
@include transition(opacity, .2s, ease-in-out);
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
&:hover {
@include opacity(1);
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.