Using the concept from waldyrious's answer, I've created the following solution that also addresses the issue of the video playing behind the image on tab restore or using the browser's back button to come back to the page with the video.
HTML
<div class="js-video-lead">
<img class="hide" src="link/to/lead/image.jpg" />
<iframe frameborder="0" height="240" src="https://www.youtube.com/embed/<code here>" width="426"></iframe>
</div>
The "hide" class is from Bootstrap and simply applies display: none;
so that the image is not visible on page load if JavaScript is disabled.
JavaScript
function video_lead_play_state(element, active)
{
var $active = $(element).closest(".js-video-lead").find(".btn-play-active");
var $default = $(element).closest(".js-video-lead").find(".btn-play-default");
if (active) {
$active.show();
$default.hide();
} else {
$active.hide();
$default.show();
}
}
$(document).ready(function () {
// hide the videos and show the images
var $videos = $(".js-video-lead iframe");
$videos.hide();
$(".js-video-lead > img").not(".btn-play").show();
// position the video holders
$(".js-video-lead").css("position", "relative");
// prevent autoplay on load and add the play button
$videos.each(function (index, video) {
var $video = $(video);
// prevent autoplay due to normal navigation
var url = $video.attr("src");
if (url.indexOf("&autoplay") > -1) {
url = url.replace("&autoplay=1", "");
} else {
url = url.replace("?autoplay=1", "");
}
$video.attr("src", url).removeClass(
"js-video-lead-autoplay"
);
// add and position the play button
var top = parseInt(parseFloat($video.css("height")) / 2) - 15;
var left = parseInt(parseFloat($video.css("width")) / 2) - 21;
var $btn_default = $("<img />").attr("src", "play-default.png").css({
"position": "absolute",
"top": top + "px",
"left": left + "px",
"z-index": 100
}).addClass("btn-play btn-play-default");
var $btn_active = $("<img />").attr("src", "play-active.png").css({
"display": "none",
"position": "absolute",
"top": top + "px",
"left": left + "px",
"z-index": 110
}).addClass("btn-play btn-play-active");
$(".js-video-lead").append($btn_default).append($btn_active);
});
$(".js-video-lead img").on("click", function (event) {
var $holder = $(this).closest(".js-video-lead");
var $video = $holder.find("iframe");
var url = $video.attr("src");
url += (url.indexOf("?") > -1) ? "&" : "?";
url += "autoplay=1";
$video.addClass("js-video-lead-autoplay").attr("src", url);
$holder.find("img").remove();
$video.show();
});
$(".js-video-lead > img").on("mouseenter", function (event) {
video_lead_play_state(this, true);
});
$(".js-video-lead > img").not(".btn-play").on("mouseleave", function (event) {
video_lead_play_state(this, false);
});
});
jQuery is required for this solution and it should work with multiple embedded videos (with different lead images) on the same page.
The code utilizes two images play-default.png
and play-active.png
which are small (42 x 30) images of the YouTube play button. play-default.png
is black with some transparency and is displayed initially. play-active.png
is red and is displayed when the user moves the mouse over the image. This mimic's the expected behavior that a normal embedded YouTube video exhibits.