Last active
February 20, 2025 09:55
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> '); | |
$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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.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; } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.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