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

web developer guide

my books

Book cover of Pro CSS3 AnimationPro CSS3 Animation, Apress, 2013

my other blogs

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

my projects

A Sass color keyword system for designers. Replaces CSS defaults with improved hues and more memorable, relevant color names.

CSSslidy: an auto-generated #RWD image slider. 3.8K of JS, no JQuery. Drop in images, add a line of CSS. Done.

tipster.ioAutomatically provides local tipping customs and percentages for services anywhere.

Here Be Dragons

Easy Custom Controls For HTML5 Video with JavaScript

javascript / video

Estimated reading time: 4 minutes, 7 seconds

Any device that supports HTML5 content must also, by definition, support HTML5 audio and video. It follows that these clients must also feature controls for AV content, initiated by using the controls attribute in your HTML. However the appearance of those controls is left up to the client: multimedia controls look quite different in IE 9 compared to Chrome. This is an issue for any designer who wishes to integrate a particular UI look-and-feel into all aspects of their website, or to make their site appear as similar as possible across different browsers and platforms.

It is entirely possible to make consistent custom AV controls for HTML5 with a little work and . Before we add any scripting, however, we should be aware of a few things:

Keeping to the best practices of graceful degradation and progressive enhancement, we will leave A/V controls on for the video by default, and then use JavaScript to turn them off and insert our own controls. The idea behind this is simple: if the client blocks JavaScript, they will still have the ability to play our audio and video content using the browser’s built-in controls. If they have JavaScript enabled, our own controls will be substituted for the defaults.

The JavaScript controls over HTML audio and video are implemented in the form of two simple methods: play() and pause(). More advanced controls such as rewind and scene access are possible, but will not be the focus of this article.

First, let’s get the basic video on the page, together with the HTML that our JavaScript will hook into. (If you’re not familiar with HTML5 video or codecs, you might want to read the associated reading list).

To create the play button, I’ll use the Unicode character “black right-pointing triangle” (U+25BA),with “black medium square” (U+25fC) representing stop, which have the advantages of very easy creation and alteration in size and color without loss of quality. I’ll integrate the controls into a figcaption element to minimize UI space.

<figure id="customcontrols">
<video controls poster="here-be-dragons.png">
<source src="here-be-dragons.m4v" type="video/mp4">
<source src="here-be-dragons.webm" type="video/webm">
<a href="#">▶</a>
<cite>Here Be Dragons</cite>

We’ll add some CSS that will hide our controls by default, and tidy up the display:

#customcontrols figcaption {
background: rgba(0,0,0,0.6);
display: none; padding: .5em;
color: #fff;
position: relative; top: -2.2rem;
text-align: right;
margin-bottom: -2.2rem;
#customcontrols figcaption a {
text-decoration: none; font-size: 1rem;
margin-right: .5rem;
color: #fff;
border-bottom: none;
#customcontrols a:hover { color: red; }
#customcontrols a:visited { color: #770; }

I’ve used relative positioning and an rgba background color to place the caption on top of the video, but made it invisible by default. In the script we’ll turn off native controls for the video and substitute our own:

var moviecontainer = document.getElementById("customcontrols"),
movie = moviecontainer.querySelector("video"),
controls = moviecontainer.querySelector("figcaption"),
playpause = controls.querySelector("a");
movie.removeAttribute("controls"); = "block";

To this code we’ll add:

playpause.addEventListener("click", function(e) {
if (movie.paused) {;
playpause.innerHTML = "◼";
} else {
playpause.innerHTML = "►";

A simple explanation: if the movie is paused, it is set to play, and the link turned to represent a stop button. Otherwise, the movie is playing, and must be paused.

comments powered by Disqus

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.