Building HTML5 video controls with JavaScript

Warning This article was written over six months ago, and may contain outdated information.

The HTML5 video element is now included in Firefox, Safari & Chrome, and on its way in Opera. By using JavaScript to access the media elements API it’s easy to build your own custom controls for it; in this article I’m going to show how I built a (very) basic control interface.

A quick disclaimer: my JavaScript is a little rusty, so may not use best practice throughout; if you can see a way my code could be better, don’t hesitate to let me know.

Anyway, here’s the finished demo.

Getting started

First you must include the video element. There are a number of attributes available, but for our purposes we need define only the src, which is the URI of our video file Update: changed the markup to use the more correct source elements inside video.

  <source src="filename.mp4">
  <source src="filename.webm">
  <source src="filename.ogg">

The video has been encoded twice, once in Theora and once in H264, to cater for different browsers; Kroc Camen’s Video for Everybody explains the reasons behind this (and how to make a bulletproof player). Update: added WebM support.

Having marked up a few controls with HTML (I’ve used id attributes on all of them to make this demo easier), the next step is to write the JavaScript to access the API (which is well explained in this article at the Mozilla Developer Center) for the controls.

The first and most important control is the play/pause button; for this I’ve written a function which checks so see if the paused attribute is true or false, and triggers the play() or pause() methods accordingly:

function playControl() {
    if (video.paused == false) {
        this.firstChild.nodeValue = 'Play';
    } else {;
        this.firstChild.nodeValue = 'Pause';

You’ll notice that it also updates the control text to indicate the action that the control will perform. There are also two function calls — pauseCount() and startCount() — which control the timer shown next to the play button.

The timer uses the currentTime and duration attributes (although the latter doesn’t seem to be currently supported by Chrome). To get the current time I’ve used setInterval to create a loop:

function startCount() {
    t = window.setInterval(function() {
        if (video.ended != true) {
            timer.firstChild.nodeValue = Math.round(video.currentTime + 1);
        } else {
            play.firstChild.nodeValue = 'Play';

First it uses an if…else statement on the ended attribute to check that the video has not finished playing; if it hasn’t, it updates the timer with currentTime (plus a little maths). If the video HAS finished, it uses clearInterval to stop the loop; this is also used in a function to pause the timer if the pause control is used:

function pauseCount() {

To complete the controls we have functions to increase and decrease the volume. Both are very similar:

function volUp() {
    if (video.volume < 1) {
        video.volume = Math.round((video.volume + 0.1)*10)/10;
        volume.firstChild.nodeValue = Math.round(video.volume*10);

First they check that the minimum/maximum limits have not been reached, and increase/decrease the volume attribute if not. Volume is on a scale of 0 to 1, and this function changes that value in increments of 0.1. The on-screen volume counter is also changed accordingly.

There are a number of small details elsewhere in the script, so feel free to have a dig through to see what else I’ve done; here’s another link to the finished demo.

Further steps

I’ve obviously used a little CSS to tidy the controls up, but a lot more could be done; using images instead of text, for example, or perhaps using something like jQuery’s user interface library to make more dynamic controls.

This article was intended only to show how easy it is to get started; what will be exciting is to see how these techniques can be expanded upon.

Update: If you found this article useful, you may be interested to know that I returned to this subject in a later post, Building a better HTML5 video player with Glow.

15 comments on
“Building HTML5 video controls with JavaScript”

  1. Hey I have a player in BETA and I still have problems with the seeking, how much has been played (buffer-bar, progress-time)


    ps how do i do this?
    (video.duration ? video.currentTime) ? 100; /* = “1.0002151″; */

  2. Hi James, take a look at my follow-up tutorial, Building A Better HTML5 Video Player With Glow, for more information about this.

    As for your second question, I’m not sure what the question marks mean in your example but if I understood it correctly it looks like you want to use Math.Round():

    Math.round((video.duration ? video.currentTime) ? 100)

    Hope that helps.

  3. […] it might be interesting to me if I get deeper into HTML5 especially by using the <video> tag. I’ve read it comes to live in combination with […]

  4. Very thanks .. I like make my own apps =)

  5. […] year Peter Gasston wrote a post (Building HTML5 video controls with JavaScript) introducing the HTML5 Media Elements API and demonstrating a simple set of controls for playing […]

  6. Brilliant job Peter!!!

  7. I’m curious if you have to have any specific AddTypes to the htaccess file? I’m using the same video types on my project and I cant get the video to play in my Android 2.0 browser. When I go to to the demo however linked on this page it plays fine.

    I have added ogv, webm and mv4 to my htaccess and when I try to play my videos on my server it says cannot play.

  8. i am trying to create a video player that i can watch live video and mark points of interest. How can i log a point of interest while video feed is coming in?

  9. In case that video is allready playing, what should i do to inicialize this correcly? Currently it will only work if i click play/pause…


  10. How would one stop the video and start it again at the beginning?
    I don’t want to pause where it is, I want to reset the position to the beginning.

  11. hello,
    This solution doesn’t work with Firefox 11 but with Chrome, it works ;)
    help me please –’

    my code source :

    var video = document.getElementById(‘videohead’);

    function playControl() {
    if (video.paused == false) {
    document.getElementById(‘playpause’).src =’./images/play.png’;
    document.getElementById(‘li_playpause’).title = ‘Play’;
    else {;
    document.getElementById(‘li_playpause’).title = ‘Pause’;

  12. Actually i’m facing a bit of problem in this i don’t really know whats causing this error..

  13. I have been asked to create a branded video player for a UofT childrens animated book. I was given a mock up with a play/stop button, a mute button and a volume contols (all would be images in a cartoon-esque theme.
    How do I bind these buttons with the players functionality? Is there an example of this somewhere?

  14. very good job peter i am trying to create a video player that i can watch live video and mark points of interest.can i make a video player which fulfill this

  15. @REM, It seems that firefox requires the properties to be called as a function for the video element. So basically if (video.paused == false) needs to be if (video.paused() == false) but subsequently, this breaks Chrome/Safari (most likely in the rendering engine Webkit).