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.

Easy Custom Controls For HTML5 Video With JQuery

javascript / video

Estimated reading time: 4 minutes, 7 seconds

Here Be Dragons

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: A/V 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 developmental 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 HTML5 audio and video are implemented in the form of two simple methods: play() and pause(). While more advanced controls such as rewind or scene access are possible, they will have to wait for a future article.

  • We’ll be adding classes to the video to keep track of whether it is playing or not. While this isn’t the most efficient way of creating a simple playback mechanism, we’ll use it to keep things simple.

  • I’m hosting the videos offsite to save on bandwidth; you may find that the webm version for Firefox is a little slow in response due to this fact.

First, let’s get the basic video on the page, together with the HTML that our will hook into. (If you’re not familiar with HTML5 video or codecs, you might want to read the related articles on this blog first). The movie is Here Be Dragons, an introduction to critical thinking presented by Brian Dunning, licensed under Creative Commons. Note that I am using the poster attribute to set a default frame for the video.

To create the play button, I’ll use the Unicode character “black right-pointing triangle” (U+25BA), and “black medium square” (U+25fC) for stop. While I could use bitmap images, the symbols 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.

<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">
<figcaption><a href="#" class="playpause">▶
</a><cite>Here Be Dragons</cite></figcaption>

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

figure { float: left; }
video { width: 470px; height: 270px; margin: 0; }
figcaption { background: rgba(0,0,0,0.6); display: none; padding: .5em; color: #fff; position: relative; top: -3.2rem; }
figcaption a { text-decoration: none; font-size: 1.5em; margin-right: .5em; vertical-align: middle; }
figcaption a:hover { color: red; }

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. After loading in JQuery, we’ll turn off native controls for the video and substitute our own:

$(document).ready(function() { 
if ($("video").attr("controls")) {

Note that we’re searching the DOM broadly, looking for any use of the video element on the page, seeing if it has a controls attribute, and removing it with JQuery’s equivalent to JavaScript’s native removeAttribute() function.

Also note that we’re adding a class (“paused”) to the video that is not referenced by anything in our CSS, just as a method of indicating that the video is paused.

To this code we’ll add:

$('a.playpause').click(function() { 
if  ($("video").hasClass('paused')) {
} else {

A simple explanation:

The video has a default class of paused applied to it. If the user clicks on a link with a class of paused, we immediately remove the paused class, and start to play the video. (Note that JQuery has to use the rather ugly $("video")[0].play).We add a play class to the video, and change the HTML content of the link with an encoded Unicode character.

If the video is playing, we remove that class, pause the video, add a class that reflect that, and change the link back to its original appearance.

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.