Introduction

Html 5 brings to life the new element which we’ll allow you to insert a native HTML video player in your web page. Unfortunately the controls of the <video> element can’t be stylized using CSS. To do that, you we’ll need to use a combination of JavaScript, CSS and HTML5 Media API (Application Programming Interface). This article is focused on creating a custom video player using the <video> element.

Content

The browsers that support the new <video> element offer access to the HTMLMediaElement interface. In this interface you can find properties, methods and events that can be used to gather information about the media elements and to control their behavior.

The methods located in HTMLMediaElement interface are:

canPlayType(string) - this method checks if the current browser can play the media type specified through the string parameter (container and codec).

- this method checks if the current browser can play the media type specified through the string parameter (container and codec). load() - this method loads your media

- this method loads your media pause() - this method pause the media play

- this method pause the media play play() - this method plays your media

The canPlayType method has as parameter a string which contains the type of media container, the type of video codec and the type of audio codec. For example, for Ogg Theora, the string parameter looks like : video/ogg; codecs=”vp8, vorbis”.

The canPlayType method returns one of the values:

probably - the browser thinks that he can play the media

maybe - the browser must try to play the media because it can’t say prior that it will work

an empty string - the browser can’t play the media

Some of the properties located in HTMLMediaElement interface are:

autoplay - Boolean attribute, true -the player will autoplay the media once that is loaded, false - autoplay is disabled; if the value of property it’s missing, is true by default

- Boolean attribute, true -the player will autoplay the media once that is loaded, false - autoplay is disabled; if the value of property it’s missing, is true by default controls - Boolean attribute, true - the controls of media player are displayed, false - the controls of media player are hidden; if the value of property it’s missing, is true by default

- Boolean attribute, true - the controls of media player are displayed, false - the controls of media player are hidden; if the value of property it’s missing, is true by default currentTime - the current time of the media play in seconds

- the current time of the media play in seconds duration - how long is the media in seconds: if this value can’t be determined, the value of this attribute will be NaN

- how long is the media in seconds: if this value can’t be determined, the value of this attribute will be NaN ended - is true if the media play is ended

- is true if the media play is ended muted - is true if the media is in mute state

- is true if the media is in mute state paused - is true if the media play is in pause state

- is true if the media play is in pause state volume - the sound volume (between 0.0 - minimum volume and 1.0 - maximum volume)

Some of the events located in the HTMLMediaElement interface are:

ended - triggered then the media had finished to play

- triggered then the media had finished to play timeupdate - triggered the the current play time is changed

Using JavaScript, CSS and the HTMLMediaElement interface we can create custom controls and we can stylize the media element.

The default buttons of native media player will be replaced by five buttons for play, pause, stop, volume up, volume down, mute/unmute functions and a progress bar for illustrate the current time of the media play.

The HTML markup for the video player element is presented in Listing 1:

Listing 1: HTML markup for the video player

<div id="container"> <video id="myVideo" width="480" height="270" preload="none" poster="big_buck_bunny.jpg" controls> <source src="video4.mp4" type="video/mp4"></source> <source src="video4.ogg" type="video/ogg"></source> <source src="video4.webm" type="video/webm"></source> </video> <div id="controls"> <button id="start">Play</button> <button id="stop" disabled>Stop</button> <button id="pause" disabled>Pause</button> <button id="plus" title="Volum" disabled>Up</button> <button id="minus" title="Volum" disabled>Down</button> <button id="mute" disabled>Mute</button> </div> <div id="progressbar"> <div id="loadingprogress"></div> <div id="butterfly"></div> </div> </div>

Because when the page is loaded, the only enabled button must be the play button, we will disable through code the other buttons.

The video element will contain the controls attribute so the users that have JavaScript disabled in browser can play the video clip.

We will stylize the page elements with CSS and we will use a gradient and a shadow for the video element and the control buttons. Using the pseudo-class hover, these shadows will glow then the video element or the control buttons are focused.

For the video element, control buttons and page background we will set transition 1 sec long and ease-in-out type, so the modification of properties will be gradually.

The progress bar and the loadingprogress element which will show the current play time of the video clip will have linear gradients for the background color.

The height of the progressbar element is fixed, but the height of the loadingprogress it will be initial 0px and then it will dynamically change through JavaScript to reflect the modification of the currentTime property.

The CSS rules used for the HTML page are presented in the listing below:

Listing 2: CSS rules used for the HTML page

<style> video{ /* video border */ border: 1px solid #ccc; padding: 20px; margin: 10px; border-radius: 20px; /* tranzitionstransitions applied to the vodeovideo element */ -moz-transition: all 1s ease-in-out; -webkit-transition: all 1s ease-in-out; -o-transition: all 1s ease-in-out; -ms-transition: all 1s ease-in-out; transition: all 1s ease-in-out; } /* background color and gradient */ video, #start, #stop, #pause, #plus, #minus, #mute { /* background color */ background-color: #ffcccc; /* background gradient */ background-image: linear-gradient(top, #fff, #fcc); background-image: -moz-linear-gradient(top, #fff, #fcc); background-image: -webkit-linear-gradient(top, #fff, #fcc); background-image: -o-linear-gradient(top, #fff, #fcc); background-image: -ms-linear-gradient(top, #fff, #fcc); } /* shadows */ video, #start, #stop, #pause, #plus, #minus, #mute { box-shadow: 0 0 10px #ccc; } video:hover, video:focus, #start:hover, #stop:hover, #pause:hover, #plus:hover, #minus:hover, #mute:hover { /* glow */ box-shadow: 0 0 20px #f88; } #controls { display: none; margin: 10px 30px; } /* style for buttons */ #start, #stop, #pause, #plus, #minus, #mute { border: 1px solid #ccc; padding: 5px; border-radius: 10px; width: 60px; margin: 0 10px 0 0; } body{ /* color tranzitiontransition */ -webkit-transition: background-color 1s ease-in-out; -moz-transition: background-color 1s ease-in-out; -o-transition: background-color 1s ease-in-out; -ms-transition: background-color 1s ease-in-out; transition: background-color 1s ease-in-out; /* initial color */ background-color: #fff; } #butterfly{ position: absolute; left: 0; top: -6px; background-image: url(butterfly.png); width: 40px; height: 40px; } #progressbar{ display: none; /* size */ width: 500px; height: 20px; /* position and border */ position: relative; border: 1px solid #ccc; margin: 10px; border-radius: 20px; /* background color */ background-color: #cccccc; /* background gradient */ background-image: linear-gradient(top, #fff, #ccc); background-image: -moz-linear-gradient(top, #fff, #ccc); background-image: -webkit-linear-gradient(top, #fff, #fcc); background-image: -o-linear-gradient(top, #fff, #ccc); background-image: -ms-linear-gradient(top, #fff, #ccc); /* shadow */ box-shadow: 0 0 10px #ccc; } #loadingprogress{ /* border */ border-radius: 20px; /* initial size */ height: 20px; width: 0; /* background color */ background-color: #9acd00; /* background gradient */ background-image: linear-gradient(top, #ffffff, #9acd00); background-image: -moz-linear-gradient(top, #ffffff, #9acd00); background-image: -webkit-linear-gradient(top, #ffffff, #9acd00); background-image: -o-linear-gradient(top, #ffffff, #9acd00); background-image: -ms-linear-gradient(top, #ffffff, #9acd00); } </style>

The JavaScript code will be executed then the page DOM is loaded using the event-handler DOMContentLoaded to attach the function called setupControl():

document.addEventListener("DOMContentLoaded", setupControl, false);

The setupControl() function checks if the browser can play the media type and if it so, the default buttons of the video element will be removed and replaced by the custom buttons. The function will enable and disable the custom control buttons to reflect the player state and it will attach the event-handlers which control the behavior of the video element.

The JavaScript code is presented in Listing 3:

Listing 3: The JavaScript code

<script> document.addEventListener("DOMContentLoaded", setupControl, false); function setupControl() { // select the video element from page var myVideo = document.getElementById("myVideo"); if (myVideo.canPlayType) { // remove the default buttons myVideo.removeAttribute("controls"); // display the custom buttons and the progress bar document.getElementById("controls").style.display="block"; document.getElementById("progressbar").style.display="block"; // add event-handlers to control the video element myVideo.addEventListener("timeupdate", reportProgress, false); myVideo.addEventListener("ended", endPlayback, false); // enable and disable the controls buttons to reflect the player state myVideo.addEventListener("play",function() { document.getElementById("start").disabled=true; document.getElementById("pause").disabled=false; document.getElementById("stop").disabled=false; document.getElementById("plus").disabled=false; document.getElementById("minus").disabled = false; document.getElementById("mute").disabled=false; }, false); myVideo.addEventListener("pause", function() { document.getElementById("start").disabled=false; document.getElementById("pause").disabled=true; document.getElementById("plus").disabled=true; document.getElementById("minus").disabled = true; document.getElementById("mute").disabled=true; }, false); // add event-handlers for the control buttons document.getElementById("start").addEventListener("click",startPlayback,false); document.getElementById("stop").addEventListener("click",stopPlayback,false); document.getElementById("pause").addEventListener("click",pausePlayback,false); document.getElementById("plus").addEventListener("click",volumeUp, false); document.getElementById("minus").addEventListener("click", volumeDown, false); document.getElementById("mute").addEventListener("click", toggleMute, false); } } //define the event-handlers // if play button is pushed, the media starts playing and the color of the page //background is changed function startPlayback() { document.getElementsByTagName("body")[0].style.backgroundColor="#664c58"; document.getElementById("myVideo").play(); } // if pause button is pushed, the media play is paused function pausePlayback() { document.getElementById("myVideo").pause(); } //if stop button is pushed, the media play stops and the current play time is reset to 0 function stopPlayback() { var myVideo = document.getElementById("myVideo"); myVideo.pause(); myVideo.currentTime=0; endPlayback(); } //if the plus button is pushed, the sound volume is increased by 10% function volumeUp() { //get the current volume var myVideo = document.getElementById("myVideo"); var volume = Math.floor(myVideo.volume * 10)/10; myVideo.muted = false; if(volume >= 0.9) myVideo.volume = 1; else myVideo.volume += 0.1; } //if the minus button is pushed, the sound volume is decreased by 10% function volumeDown() { //get the current volume var myVideo = document.getElementById("myVideo"); var volume = Math.floor(myVideo.volume * 10)/10; myVideo.muted = false; if(volume <= 0.1) myVideo.volume = 0; else myVideo.volume -= 0.1; }m //if the mute button is pushed, the player wilwill toggle between Mute and Unmute state function toggleMute() { var myVideo = document.getElementById("myVideo"); var mute = document.getElementById("mute"); if(myVideo.muted) { mute.innerHTML = "Mute"; myVideo.muted = false; } else { mute.innerHTML= "Unmute"; myVideo.muted = true; } } // when the media play is finished or stopped function endPlayback() { // reset the color of page background document.getElementsByTagName("body")[0].style.backgroundColor="#fff"; // reset the progress bar var progress = document.getElementById("butterfly"); progress.style.left="-10px"; // reset the state of buttons document.getElementById("start").disabled=false; document.getElementById("pause").disabled=true; document.getElementById("stop").disabled=true; } // update the progress bar function reportProgress() { var barwidth = 500; var sliderwidth = 30; // get current time var time = Math.round(this.currentTime); //get the media play time var duration = parseInt(this.duration); //calculate the position on the progress bar var position = barwidth * (time / duration); if (isNaN(position)) return; //update the progress bar document.getElementById("loadingprogress").style.width=position + "px"; // update the position of the butterfly var butterfly = document.getElementById("butterfly"); if (position <= (barwidth - Math.round(sliderwidth / 2))) { butterfly.style.left=position + "px"; } else { butterfly.style.left=barwidth - Math.round(sliderwidth / 2); } } </script>

The next print screens illustrate the initial aspect of the page (soon after loading) and the aspect of the page after the media starts playing:

Figure 1: Example 1

Figure 2: Example 2

Conclusion

Using the right combination of CSS and JavaScript a rather boring page can be transform in a dynamic page which will attract the users through aspect and functionality.

Another resources: