One of my favorite things about HTML5 video is how easy it is to create your own custom controls. This not only allows you to style the controls however you would like but also allows you to add new controls like fast-forward or rewind. This is all done through the use of a JavaScript API.
In this post you are going to learn how to build your own custom controls for HTML5 videos.
Lets get started!
You can download a copy of all the assets used in this blog post here.
NOTE: A few weeks ago I wrote a post that covered how to get started with HTML5 video. If you haven’t used HTML5 video before I would recommend that you give that post a read first. Go ahead, I’ll wait.
Contents
Setting up your HTML5 Video
The first thing you need to do is write some HTML for your video and the controls. In the spirit of being truly cutting edge I’ve opted to use range inputs for the sliders but just be aware that these are not supported in all browsers yet.
You can download the video files and a stylesheet for this demo here.
<div id="video-container"> <!-- Video --> <video id="video" width="640" height="365"> <source src="videos/mikethefrog.webm" type="video/webm"> <source src="videos/mikethefrog.ogv" type="video/ogv"> <source src="videos/mikethefrog.mp4" type="video/mp4"> <p> Your browser doesn't support HTML5 video. <a href="videos/mikethefrog.mp4">Download</a> the video instead. </p> </video> <!-- Video Controls --> <div id="video-controls"> <button type="button" id="play-pause">Play</button> <input type="range" id="seek-bar" value="0"> <button type="button" id="mute">Mute</button> <input type="range" id="volume-bar" min="0" max="1" step="0.1" value="1"> <button type="button" id="full-screen">Full-Screen</button> </div> </div>
Here you have created play/pause, mute and full screen buttons as well as two sliders. One that will be used to skip through the video and another to control the volume.
That’s all the HTML that you are going to need to get things working. If you view this in a web browser you should see the video on the page. When you hover over the video with your mouse cursor the controls should appear, as shown in the figure below. This hover effect is achieved using CSS and CSS3 transitions.
Setting up the JavaScript
Lets dive into writing the JavaScript that will bring your video controls to life.
Create a new JavaScript file called script.js
and link it up to your HTML page using a <script>
element.
<script src="script.js"></script>
Now open up this JavaScript file and add the following code to it.
window.onload = function() { // Video var video = document.getElementById("video"); // Buttons var playButton = document.getElementById("play-pause"); var muteButton = document.getElementById("mute"); var fullScreenButton = document.getElementById("full-screen"); // Sliders var seekBar = document.getElementById("seek-bar"); var volumeBar = document.getElementById("volume-bar"); }
Here you have created a number of variables and initialized them with the video and controls from your HTML markup.
The first video control we are going to tackle is the play/pause button. To get this working you will need to set up an event listener that checks whether the video is currently playing and then toggles playback appropriately. You can check the paused
property of your video to examine the current playback state. Use the play()
and pause()
functions to control playback.
// Event listener for the play/pause button playButton.addEventListener("click", function() { if (video.paused == true) { // Play the video video.play(); // Update the button text to 'Pause' playButton.innerHTML = "Pause"; } else { // Pause the video video.pause(); // Update the button text to 'Play' playButton.innerHTML = "Play"; } });
Here you have set up an event listener for the click
event on your play/pause button and used an if
statement to toggle the video playback. You’ve also added some code that will update the text displayed on the button.
To get the mute button working you need to follow a similar process to the one you used for the play/pause button. This time however you need to examine the muted
property of the video and toggle its value appropriately.
// Event listener for the mute button muteButton.addEventListener("click", function() { if (video.muted == false) { // Mute the video video.muted = true; // Update the button text muteButton.innerHTML = "Unmute"; } else { // Unmute the video video.muted = false; // Update the button text muteButton.innerHTML = "Mute"; } });
When the mute button is clicked this event listener will toggle the value of the muted
property. You have also added some code that will update the button text.
Kicking it Full-Screen
Many modern web browsers have implemented a FullScreen API that allows you to give full screen focus to certain HTML elements. This is really great for displaying interactive media like videos in a fully immersive environment.
To get the full screen button working you need to set up another event listener that will call the requestFullScreen()
function when the button is clicked. To ensure that this will work across all supported browsers you are also going to need to check to see if the requestFullScreen()
is available and fallback to the vendor prefixed versions (mozRequestFullScreen
and webkitRequestFullscreen
) if it is not.
// Event listener for the full-screen button fullScreenButton.addEventListener("click", function() { if (video.requestFullscreen) { video.requestFullscreen(); } else if (video.mozRequestFullScreen) { video.mozRequestFullScreen(); // Firefox } else if (video.webkitRequestFullscreen) { video.webkitRequestFullscreen(); // Chrome and Safari } });
Now if you reload the page and click the full screen button it should launch the video into full screen view. Pretty neat.
Hooking up the Seek Bar
That’s all the buttons sorted. Now lets take a look at that seek bar. This one gets a little more complicated so we’re going to approach it in three phases.
To start with lets hook it up so that dragging the slider handle changes the position in the video. To do this you need to set up an event listener on the seekBar
that will execute when the change
event is fired. You then need to calculate the time in the video that playback should be skipped to and update the time of the video accordingly.
// Event listener for the seek bar seekBar.addEventListener("change", function() { // Calculate the new time var time = video.duration * (seekBar.value / 100); // Update the video time video.currentTime = time; });
Here you have calculated the time by taking the total duration of the video (accessed using the duration
property) and multiplying that by the value of the seekBar
divided by 100. To update the position in the video you set the currentTime
property of the video to the time you just calculated.
This basic implementation works but you might have noticed that the position of the slider handle doesn’t move as the video plays. To fix this you need to set up an event listener on the video
that executes when the timeupdate
event is fired. You then reverse the calculation that was used previously in order to get the value that the seekBar
should be set to. The timeupdate
event is fired continuously as the video plays.
// Update the seek bar as the video plays video.addEventListener("timeupdate", function() { // Calculate the slider value var value = (100 / video.duration) * video.currentTime; // Update the slider value seekBar.value = value; });
Now if you reload the page and start the video you should see that the slider handle moves along as the video plays!
There’s just one more bug that we need to fix with the seek bar. If you slowly drag the slider handle you will notice that the video keeps trying to play, resulting in a stuttering playback. To fix this you need to pause the video when the slider handle starts to be dragged and then play it again once the handle is dropped. You can do this by using two event listeners that execute when the mousedown
and mouseup
events are fired. Pause the video on mousedown
and play it again on mouseup
.
// Pause the video when the slider handle is being dragged seekBar.addEventListener("mousedown", function() { video.pause(); }); // Play the video when the slider handle is dropped seekBar.addEventListener("mouseup", function() { video.play(); });
Hooking up the Volume Control
The final control to implement is the volume slider. For this you need to set up an event listener for the change
event. When this event fires you just need to take the value from the slider and use it to update the value of the volume
property on the video.
The volume
property should always have a value between 0 and 1. If you look back at your HTML markup you can see that we used the min
and max
attributes on the volume input to enforce this requirement.
// Event listener for the volume bar volumeBar.addEventListener("change", function() { // Update the video volume video.volume = volumeBar.value; });
That’s it! Congratulations, you just created your very own controls for a HTML5 video.
HTML5 video opens up a lot of cool new opportunities for developers. Being able to easily create your own custom controls is just one of them. Take a look at some of the demos on HTML5Rocks for inspirational on where you can go from here.
If you build some cool looking controls for your videos post a link in the comments below. It would be awesome to see them!