I'm Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with HTML, CSS and SVG. To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

my books

Pro CSS3 Animation book coverPro CSS3 Animation, Apress, 2013

my other blogs

Massive Head CanonMassive Head Canon: Intelligent discussion of movies, books, games, and technology.

my projects

The New DefaultsThe New Defaults — A Sass color keyword system for designers.

CSSslidyCSSslidy — an auto-generated #RWD image slider. 3.8K of JS, no JQuery.

Create A Simple HTML5 Video Playlist

Easy, responsive, and progressive.

Last week two of my students wanted to know if there was a way to create a HTML5 video playlist without using a third-party service such as YouTube. They also wanted a responsive solution that would be easy to implement.

One possible answer is to use PHP to generate URL variables for a <video> element, an approach similar to the one I’ve provided in the simple server-side image gallery. There are also many JQuery plugin candidates, but it seemed excessive to load in a 100K framework just to create a playlist. Instead, I opted to show the students a solution using native JavaScript, using the principles of progressive enhancement.

The easiest way to start development on the video playlist is to work from the base HTML upwards. For this example I’ll reference outtakes from Marsel Van Oosten’s and Daniella Sibbing’s spectacular astrophotography timelapse Nambian Nights, licensed under Creative Commons.

Writing The Base HTML

The construction of the HTML makes the simple assumption that the CSS and JavaScript we add later will fail to work as intended. Obviously, that’s not what we want to happen, but it’s the pragmatic default state. HTML is the base layer of our web page: if we build that to serve as many visitors as possible, then CSS and JavaScript can be considered an enhancement to the basic experience. Keeping this approach in mind, our markup looks something like this:

<figure id="video_player">
<video controls poster="nambia1.jpg">
<source src="nambia1.mp4" type="video/mp4">
<source src="nambia1.webm" type="video/webm">
</video>
<figcaption>
<a href="nambia1.mp4"><img src="nambia1.jpg" alt="Nambia Timelapse 1"></a>
<a href="nambia2.mp4"><img src="nambia2.jpg" alt="Nambia Timelapse 2"></a>
<a href="nambia3.mp4"><img src="nambia3.jpg" alt="Nambia Timelapse 3"></a>
</figcaption>
</figure>

(For the same of clarity, I’m placing all files in the same location. I’m also assuming that all browsers using the page understand HTML5 video: if that assumption was unreasonable, there are further fallbacks I could write in).

The links go directly to the .mp4 version of the videos, which will be displayed in the majority of browsers. The result won’t look pretty, nor does it have the interactivity we want, but it does work. Our next step is to enhance the presentation of the playlist with CSS.

Creating A Responsive Solution

Ideally, we want the three thumbnail links to be displayed in a dimmed state beside the main video. Hovering will brighten the links. I’ll use display: table together with percentage measurements to achieve this:

#video_player { display: table; line-height: 0; font-size: 0; background: #000; }
#video_player video, #video_player figcaption { display: table-cell; vertical-align: top; }
#video_player figcaption { width: 25%; }
#video_player figcaption a { display: block; opacity: .5;
transition: 1s opacity; }
#video_player figcaption a img, figure video { width: 100%; height: auto; }
#video_player figcaption a:hover { opacity: 1; }

If the browser is less than 700 pixels wide, it makes sense to display the thumbnails below the main video:

@media (max-width: 700px) {
#video_player video, #video_player figcaption { display: table-row; }
#video_player figcaption a { display: inline-block; width: 33.33%; }
}

With the basic presentation rules done, it’s time to add the JavaScript.

Adding Interactivity

The first task is to ensure that all of the links inside the video respond in the same way to a click. At the bottom of the page, we start our script with:

var video_player = document.getElementById("video_player");
var links = video_player.getElementsByTagName('a');
for (var i=0; i<links.length; i++) {
links[i].onclick = handler;
}

… then add the handler function that we’ve just add to each link. I’ll show the complete function here, and explain it in a moment:

function handler(e) {
e.preventDefault();
videotarget = this.getAttribute("href");
filename = videotarget.substr(0, videotarget.lastIndexOf('.')) || videotarget;
video = document.querySelector("#video_player video");
video.removeAttribute("controls");
video.removeAttribute("poster");
source = document.querySelectorAll("#video_player video source");
source[0].src = filename + ".mp4";
source[1].src = filename + ".webm";
video.load();
video.play();    
}

This script does several things:

  1. Prevents the user’s click on a link from engaging the default behavior: so long as the user is running JavaScript, clicking on the link will no longer take them directly to the referenced .mp4 file.
  2. Looks at the filename referenced in the clicked link’s href attribute.
  3. Splits the filename and captures everything before the last period, giving us the path and name of the file without an extension. (This assumes that the files are named correctly, and that we have been consistent when naming related .mp4 and .webm files.)
  4. Finds the <video> element and removes its poster image and controls.
  5. Finds the <source> elements for the video and sets them to the appropriate filename that we derived from steps 2 and 3.

There’s much more we can do to this simple playlist example. Autoplaying the next video in the sequence is an obvious first step, as is returning the player controls when the user is hovering over the <video> element. There’s also the possibility of using a single video rather than several separate ones, using HTML5 technologies to jump to different cuepoints in the video on click. I’ll address these features and more in upcoming articles.

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.