Skip to content

Instantly share code, notes, and snippets.

@ttscoff
Last active January 26, 2020 17:57
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ttscoff/5940744 to your computer and use it in GitHub Desktop.
Save ttscoff/5940744 to your computer and use it in GitHub Desktop.
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.
# 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)
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+"/maxresdefault.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();
.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; }
.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);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment