Design, CG Graphics & Inspiration
How to Make Your Own Video Player On HTML5 Video

How to Make Your Own Video Player On HTML5 Video

Today we are going to cope with the task of creating your own video player on HTML5 Video. Let me remind you that the video-element by itself already provides the necessary set of controls for playback controlling. In order you could see the playback control panel, it’s necessary to set the controls attribute.

<video src="trailer_480p.mp4" width="480" height="270" poster="poster.gif" controls />

However, there is a problem with the standard controls the difficulty is lies in the fact that they have a nonstandard look. In other words, in every browser, they look differently (you can check out how the controls look like in different browsers on the example of the Video Format Support – just open it in two or three different browsers).

API for Playback Control

HTML5 standard for video introduces a new interface in the DOM – HTMLVideoElement, which in its turn inherits interface from HTMLMediaElement.

HTMLMediaElement Interface

This is a common interface for both media elements (audio and video) which describes the access to basic features for working with the media content: control of the content source, playback control, changing the sound level and error handling. The main properties and methods that we’ll need:

Network status and availability performance

src – link (url) for playing content
buffered – buffered chunks of video

Playback and controls

currentTime – the current time of playback (sec.)
duration – the duration of media content (sec.)
paused – whether the playing is on a pause
ended – whether the playing ended or not
muted – on / off the sound
volume – the sound level [0, 1]
play () – start playback
pause () – pause


oncanplay – you can start playing
ontimeupdate – the position of playing is changed
onplay – media player is running
onpause – paused
onended – playing is over

Important: it is not all methods and properties that can be implemented with HTMLMediaElement interface.

HTMLVideoElement Interface

Video differs from the audio in several additional properties:

width and height – width and height of the container for video playback;
videoWidth and videoHeight – internal width and height of the video, if the dimensions are not known, than they equal to 0;
poster – link to an image that can be shown so far video is not available (usually one of the first non-empty frames).

The difference between the width / height and videoWidth / videoHeight is that the last one are their own characteristics of video, in particular, the aspect ratio and other characteristics, while the container for the video can be of any size (larger, smaller, of the other ratio.)

Play & Pause

We’ll start the creation of our own video player with a simple task: learn how to run the video on playback and stop the playback. To do this we need play () and pause () methods and several properties that describe the current state of the video stream (we’ll also use the jQuery library, do not forget to connect it).

The first thing we need is video-element, which we want to control, and an element which can be pressed to control the current state:

    <video id="myvideo" width="480" height="270" poster="poster.gif" >
        <source src="trailer_480p.mp4" type='video/mp4;codecs="avc1.42E01E, mp4a.40.2"' />
        <source src="trailer_480p.webm" type='video/webm; codecs="vorbis,vp8"'/> 
<div id="controls">
    <span id="playpause" class="paused" >Play</span>

#controls span {
#playpause {
    padding:0 5px;

Note the state’s inversion of the (pause) button and the (play) action.

Now we should add a bit of js-code so that with clicking the play button its state will switch, and accordingly run a video-clip or put it on a pause:

    var controls = {
        video: $("#myvideo"),
        playpause: $("#playpause")                 
    var video =[0];
        if (video.paused) {
        } else {

If desired, you can immediately add some css-styles for buttons and their various states. It might seem that everything is cool and works fine, but that’s not how it turns out! There are a few details that we also need to consider.

Playing again from the beginning

First, we need to properly handle the end of the video playback (unless, of course, it is not fixated), and at this point to switch the buttons so that instead of the state «pause» was the state «play»:

video.addEventListener("ended", function() {

Context menu

Second, browsers typically add the ability to control playback via the context menu. This means that generally user can make changes bypassing our controls. This point should be also mentioned and the necessary changes to the appearance of controls should be applied too. It’s enough to subscribe to onplay and onpause events.

video.addEventListener("play", function() {
video.addEventListener("pause", function() {

Since we have got too many changes in appearance, it’s time to make a small refactoring along the way by removing from the original mode switching a duplicate replacement of the external condition:

var controls = {
    togglePlayback: function() {
        (video.paused) ? : video.pause();

Clickable video

Surely, you would like to switch between play and pause by clicking on the video itself, so you’ll need to add a few lines: {

Current result:
current_result in How to Make Your Own Video Player On HTML5 Video


Now let’s move on to the display of progress playing. First we need to add a few items that will be used to display the current status and management of the current position:

<span id="progress">
    <span id="total">
        <span id="buffered"><span id="current">​</span></span>
<span id="time">
    <span id="currenttime">00:00</span> / 
    <span id="duration">00:00</span>

Appropriate styles:

#progress {
#total {
#buffered {
#current {
#time {

And a few references to the appropriate elements for quick access to the controls object:

var controls = {
    total: $("#total"),
    buffered: $("#buffered"),
    progress: $("#current"),
    duration: $("#duration"),
    currentTime: $("#currenttime"),
    hasHours: false,

The first thing we need to understand is what is the duration of the movie – for this purpose video-element has a duration property. To track this value is possible, for example, at the moment when the clip is ready for the playback – with the help of oncanplay event:

video.addEventListener("canplay", function() {
    controls.hasHours = (video.duration / 3600) >= 1.0;                    
    controls.duration.text(formatTime(video.duration, controls.hasHours));
}, false);

In this case, we simultaneously determine whether to display the number of hours in video player (generally speaking, the specification suggests that the duration of the clip can be changed -at this moment fires the ondurationchange event, and also be infinite – for example, streaming radio).

function formatTime(time, hours) {
    if (hours) {
        var h = Math.floor(time / 3600);
        time = time - h * 3600;
        var m = Math.floor(time / 60);
        var s = Math.floor(time % 60);
        return h.lead0(2)  + ":" + m.lead0(2) + ":" + s.lead0(2);
    } else {
        var m = Math.floor(time / 60);
        var s = Math.floor(time % 60);
        return m.lead0(2) + ":" + s.lead0(2);
Number.prototype.lead0 = function(n) {
    var nz = "" + this;
    while (nz.length < n) {
        nz = "0" + nz;
    return nz;

To display the process of playing, we need the ontimeupdate event, which fires when changing the current moment:

video.addEventListener("timeupdate", function() {
    controls.currentTime.text(formatTime(video.currentTime, controls.hasHours));
    var progress = Math.floor(video.currentTime) / Math.floor(video.duration);
    controls.progress[0].style.width = Math.floor(progress * + "px";
}, false);

CurrentTime property displays the current time in seconds. It also can be used to change the playback time: {
    var x = (e.pageX - this.offsetLeft)/$(this).width();
    video.currentTime = x * video.duration;

It will be also useful to show the video buffering, this can be done by using onprogress event, which fires when loading new portions of the video:

video.addEventListener("progress", function() {
    var buffered = Math.floor(video.buffered.end(0)) / Math.floor(video.duration);
    controls.buffered[0].style.width =  Math.floor(buffered * + "px";
}, false);

An important nuance regarding the property buffered, which must be kept in mind is that it provides not only time, in seconds, and time intervals in the form of TimaRanges object. In most cases it will be only one period with an index of 0, and starting with a mark of 0sec.
However, if the browser uses HTTP range requests to the server, for example, in response to attempts to switch to other fragments of the video stream, there might be several gaps. It also should be taken into account that depending on the implementation, the browser can remove already played chunks of video from the buffer.

Intermediate result:
Intermediate_result in How to Make Your Own Video Player On HTML5 Video

The Sound

Finally, let’s add a little touch to our video player – ability to enable or disable the sound. To do this, we’ll add a little control to with a speaker (SVG-icon taken from the site The Noun Project):

<span id="volume">
    <svg id="dynamic" version="1.0" id="Layer_1" xmlns="" xmlns:xlink="" x="0px" y="0px"
	 width="16px" height="16px" viewBox="0 0 95.465 95.465">
        <g >
            <polygon points="39.323,20.517 22.705,37.134 0,37.134 0,62.865 22.705,62.865 39.323,79.486 "/>
            <path d="M52.287,77.218c14.751-15.316,14.751-39.116,0-54.436c-2.909-3.02-7.493,1.577-4.59,4.59
            <path d="M62.619,89.682c21.551-22.103,21.551-57.258,0-79.36c-2.927-3.001-7.515,1.592-4.592,4.59
            <path d="M75.48,99.025c26.646-27.192,26.646-70.855,0-98.051c-2.936-2.996-7.524,1.601-4.592,4.59

With the appropriate styles for both on and off states:

#dynamic {
    padding:0 5px;

To switch the state of the dynamic we’ll need the mute property: {
    var classes = this.getAttribute("class");

    if (new RegExp('\\boff\\b').test(classes)) {
        classes = classes.replace(" off", "");
    } else {
        classes = classes + " off";

    this.setAttribute("class", classes);
    video.muted = !video.muted;

Standard jQuery methods for toggling css-class do not work with SVG-elements. If you want to change the volume, then you will need the volume property, which takes values over the range of [0, 1].

The final result:
final_result in How to Make Your Own Video Player On HTML5 Video

And some more…

Besides the fact that you can easily set the styles of the control elements on your own, there are a few important points that remain outside the article, but they are very useful to be remembered about in a real project:

• whether the browser supports HMTL5 Video or not,
software definition and switching of supported codecs,
• support for subtitles, including the accessibility support.

Also don’t forget that you should do the binding of events to the control elements after it became clear that the video is available for playback (oncanplay):

video.addEventListener("canplay", function() {
}, false);

Also you should do the appropriate checks or capture the possible exceptions. Generally, you should always pay attention to such exceptions as onerror event, which occurs when there is an error of loading the video stream.

And the additional option that you might need is changing the playback speed. Especially for this case there is a playbackRate property and the corresponding onratechange event.

Ready-made Players

I think it won’t be difficult for you to find some ready-made solutions for HTML5 Video with all relying features, up to a comfortable appearance customization via CSS. Here are some useful links:

JW Player
LeanBack Player
HTML5 Video Player Comparison

Finally, HTML5 Video in specifications.

To read original article in Russian click here.

You might also be interested in..

HTML5 Essentials Resources
HTML5 Placeholder stylization with the help of CSS
15 Handy HTML5/CSS3 Frameworks For Web Developers
20 Free HTML5 Games
Meet The Future – HTML5 Demos
HTML5 video players
Content editable Feature in HTML5

  • Constantin Kichinsky,
  • September 7, 2011


I`m working at Microsoft Russia as Academic Developer Evangelist. If you are intrested in my thoughts related to my work look at and

Subscribe for the hottest posts

Subscribe to our email newsletter for useful tips and freebies.

  • Web Design Company Mumbai

    Nice Tutorial.

  • emgerold

    Yeah nice one! Thanks a lot.

  • Michael

    Great tutorial.
    Can you do this as a splash screen as the page loads too?

  • Andrea Chrenova

    Oh great tutorial, im searching for the code to make controls of video from my own images, can you help me? Where should i define img src?

  • Cristian De la Hoz

    Hey parce muchas gracias…

  • James Church

    Hi! very good tutorial, Its exactly what I needed! I’ve used the Play & Pause section to create the JS code I needed for a web development I am doing.

    All works well on Safari and Chrome, however it is not working in Firefox. In the error console it is saying that and video.pause are not a function. Have you any idea on how to solve this?

    Thank you


  • Gest

    it dosent work on my pc:(

  • CW

    Thanks for the valuable post. Before reading this post, I tried out a few techniques to create a video but didn’t actually click. Now I think I have got a better idea on how to go about it. let me just try and implement these steps and make my video. I will get back to this post once I make my first video. Thanks

  • Sharon Thomas

    This is a wonderful tutorial. Your post gives us a clear idea on how to create videos. This is an interesting thing that I love doing. Thank you so much for the step by step explanation. Sound is always a problem in my videos. I think this is going to solve them.

  • Bennet_Marky

     Nice informative blog. I really liked the video. From where did u get the video.I liked the bunny in it. Thanks for the tutorial.

  • Mrinal

    Nice tutorial! Thanks

  • Dakota Reno

    Source code please?

  • 000000000000000000000000000001

    Thanks!! This Realy Works !