With the introduction of HTML 5, the audio tag provides a simple way to play audio files without the use of Adobe Flash. However, with the generic controls attribute, all audio tags look the same, but without any controls defined, the audio tag is invisible. In this tutorial I provide examples and a simple library on interacting with the audio element through Javascript and CSS. This provides the developer the ability to stylize all of the buttons and make a custom UI for the Audio element.

Update 5-25-2017
We’ve made it even easier for you to style HTML5 audio elements. Amplitude 3 is now available! Download it on GitHub. Check out the Amplitude site for latest documentation and a to see the latest features:

GetAmplitude-1

The Audio Element

The audio tag has a few events that you can run functions off of and a source tag which contains the path to the song you want to play along with the type of the song.

<audio id="song" width="300" height="32" ontimeupdate="updateTime()"><source src="path/to/music.mp3" type="audio/mp3" /></audio>

For an extreme in depth look into the audio tag, check out http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#audio. A lot of our functions will run off of the ontimeupdate action handler which calls the updateTime() function. If you want to use the standard controls that are predefined, just put the boolean “controls” into the audio tag. It goes against the entire scope of this article, but if that’s a route you wish to take, you can do that as well.

<audio id="song" width="300" height="32" ontimeupdate="updateTime()" controls="controls"><source src="path/to/music.mp3" type="audio/mp3" /></audio>

The Controls

There are a certain set of controls that are necessary to completely interact with the audio tag. I recreated the most common ones:

  • Play
  • Pause
  • Play/Pause
  • Stop
  • Volume Up, Down
  • Volume Meter
  • Song Meter and Time Tracker

Play Button

The play button has simple functionality, it starts playing the song. In the library I constructed, it also sets the active song variable. This makes sense because every other function depends on the fact that the song is playing before it gets interacted with. As a parameter the play method accepts the id of the audio tag to start and stop the song.

Javascript

var activeSong;
//Plays the song. Just pass the id of the audio element.
function play(id){
  //Sets the active song to the song being played. All other functions depend on this.
  activeSong = document.getElementById(id);
  //Plays the song defined in the audio tag.
  activeSong.play();

  //Calculates the starting volume percentage of the song.
  var percentageOfVolume = activeSong.volume / 1;
  var percentageOfVolumeMeter = document.getElementById('volumeMeter').offsetWidth * percentageOfVolume;

  //Fills out the volume status bar.
  document.getElementById('volumeStatus').style.width = Math.round(percentageOfVolumeSlider) + "px";
}

A note to keep in mind is the fact that the volume is on a 0-1 scale. That means 50% volume is represented as .5. With the volume status and meter, the meter is how much volume can be applied and the status is the current volume level.

#songPlay{

}
<div id="songPlay" onclick="play('song')"></div>

With the CSS you can style the songPlay div anyway you like. For example, you can define a background color, image, etc. With the HTML, all you have to do is define the “songPlay” div and then define the onclick action handler to call the play function and pass the id of the audio tag.

Pause Button

The pause button has a very simple function. It pauses the active song. Since the active song is set by the play button, all the pause button does is pause it so it doesn’t need any parameters.

#songPause{

}
<div id="songPause" onclick="pause()"></div>
//Pauses the active song.
function pause(){
  activeSong.pause();
}

The html simply calls the pause function when clicked. The onclick action handler calls the javascript function to pause the song.

Play/Pause Button

The play/pause button cycles duties based off of the current state of the song. If the song is playing, the song gets paused the next time it is clicked. If the song is paused, it plays the next time the button is clicked. Since the song could be playing for the first time, we need to pass the id of the song as a parameter and set the active song variable to it.

//Does a switch of the play/pause with one button.
function playPause(id){

  //Sets the active song since one of the functions could be play.
  activeSong = document.getElementById(id);

  //Checks to see if the song is paused, if it is, play it from where it left off otherwise pause it.
  if (activeSong.paused){
    activeSong.play();
  }else{
    activeSong.pause();
  }
}

Since CSS doesn’t recognize the state of the song, any changes you want to make to the button’s look in the form of colors or images has to be done with Javascript.

#songPlayPause{

}
<div id="songPlayPause" onclick="playPause('song')"></div>

Like I mentioned earlier, since the play/pause function could be starting the song for the first time, we need to pass it the id of the audio element so it can set the active audio element to the one that we are interacting with.

Stop Button

The stop button is pretty simple, it stops the song by setting the song current time back to zero and then pausing it. This simulates the stop event.

//Stop song by setting the current time to 0 and pausing the song.
function stopSong(){
  activeSong.currentTime = 0;
  activeSong.pause();
}
#songStop{

}
<div id="songStop" onclick="stopSong()">Stop</div>

Volume Up and Down Buttons

With the volume up and volume down buttons, there is a single function where you pass the direction you want the volume as one parameter and the increment/decrement size as the other parameter. To adjust the size of the increase/decrease, just change the value in the function call.

//Changes the volume up or down a specific number
function changeVolume(number, direction){
  //Checks to see if the volume is at zero, if so it doesn't go any further.
  if(activeSong.volume >= 0 && direction == "down"){
    activeSong.volume = activeSong.volume - (number / 100);
  }

  //Checks to see if the volume is at one, if so it doesn't go any higher.
    if(activeSong.volume activeSong.volume = activeSong.volume + (number / 100);
  }

  //Finds the percentage of the volume and sets the volume meter accordingly.
  var percentageOfVolume = activeSong.volume / 1;
  var percentageOfVolumeSlider = document.getElementById('volumeMeter').offsetWidth * percentageOfVolume;

  document.getElementById('volumeStatus').style.width = Math.round(percentageOfVolumeSlider) + "px";
}

The volume status slider is filled based off of a percentage of volume currently being used and the size of the volume status div.

/*Volume Up Button*/
#volumeUp{

}
/*Volume Down Button*/
#volumeDown{

}
<div id="volumeUp" onclick="changeVolume(10, 'up')"></div>
 
<div id="volumeDown" onclick="changeVolume(10, 'down')"></div>

Volume Meter

The volume meter simply displays to the user the status of the volume being used to play the song. The meter also allows the user to click and adjust the volume accordingly.

//Set's volume as a percentage of total volume based off of user click.
function setVolume(percentage){
  activeSong.volume = percentage;

  var percentageOfVolume = activeSong.volume / 1;
  var percentageOfVolumeSlider = document.getElementById('volumeMeter').offsetWidth * percentageOfVolume;

  document.getElementById('volumeStatus').style.width = Math.round(percentageOfVolumeSlider) + "px";
}

//Set's new volume id based off of the click on the volume bar.
function setNewVolume(obj,e){
  var volumeSliderWidth = obj.offsetWidth;
  var evtobj = window.event? event: e;
  clickLocation = evtobj.layerX - obj.offsetLeft;

  var percentage = (clickLocation/volumeSliderWidth);
  setVolume(percentage);
}

You can set the width of the volume status bar in the CSS. The javascript gets the location of the click on the horizontal bar, by getting the click location and subtracting the offset from the left. Once the percentage is calculated, the setVolume function is called and the percentage is passed to it. In that function, the active song volume is set and the visual display is updated accordingly.

/*Volume Meter*/
#volumeMeter{

}
/*Volume Location Meter*/
#volumeStatus{

}
<div id="volumeMeter" onclick="setNewVolume(this,event)"></div>

Song Meter and Time Tracker

The song meter (in minutes and seconds) and the visual position go hand in hand. The main purpose is to show the current location of the song in time and visual percentage. All of this gets updated with the ontimeupdate event handler that is set within the audio tag. Every time the current location of the song is updated, the method set in the ontimeupdate handler gets called. This change can come from the user clicking on the song position bar we set or just the update of time as the song plays on. In this case the event handler is set to run the updateTime() function.

//Updates the current time function so it reflects where the user is in the song.
//This function is called whenever the time is updated. This keeps the visual in sync with the actual time.
function updateTime(){
  var currentSeconds = (Math.floor(activeSong.currentTime % 60) < 10 ? '0' : '') + Math.floor(activeSong.currentTime % 60);
  var currentMinutes = Math.floor(activeSong.currentTime / 60);

  //Sets the current song location compared to the song duration.
  document.getElementById('songTime').innerHTML = currentMinutes + ":" + currentSeconds + ' / ' + Math.floor(activeSong.duration / 60) + ":" + (Math.floor(activeSong.duration % 60) < 10 ? '0' : '') + Math.floor(activeSong.duration % 60);

  //Fills out the slider with the appropriate position.
  var percentageOfSong = (activeSong.currentTime/activeSong.duration);
  var percentageOfSlider = document.getElementById('songSlider').offsetWidth * percentageOfSong;

  //Updates the track progress div.
  document.getElementById('trackProgress').style.width = Math.round(percentageOfSlider) + "px";
}

/*
Gets the percentage of the click on the slider to set the song position accordingly.
Source for Object event and offset: http://website-engineering.blogspot.com/2011/04/get-x-y-coordinates-relative-to-div-on.html
*/
//Sets the location of the song based off of the percentage of the slider clicked.
function setLocation(percentage){
  activeSong.currentTime = activeSong.duration * percentage;
}
/*
Gets the percentage of the click on the slider to set the song position accordingly.
Source for Object event and offset: http://website-engineering.blogspot.com/2011/04/get-x-y-coordinates-relative-to-div-on.html
*/
function setSongPosition(obj,e){
  //Gets the offset from the left so it gets the exact location.
  var songSliderWidth = obj.offsetWidth;
  var evtobj=window.event? event : e;
  clickLocation = evtobj.layerX - obj.offsetLeft;

  var percentage = (clickLocation/songSliderWidth);
  //Sets the song location with the percentage.
  setLocation(percentage);
}

The updateTime method sets the span that has the visual time is displayed in. The setLocation and setSongPosition methods work hand in hand if the user clicks to skip ahead in the song. The setSongPosition handles the place where the user clicks on the position tracker. Once the percentage is found, the setLocation method is called and sets the location in the song based off of percentage of song duration compared to location clicked on the song tracker.

/*Song location slider*/
#songSlider{

}
/*Track progress bar*/
#trackProgress{

}
<!-- Song Slider tracks progress on song time change, if you click it sets the distance into the song
based on the percentage of where was clicked -->
<div id="songSlider" onclick="setSongPosition(this,event)"></div>

The Library

To download the library click here. Feel free to use and play around with any of the functions (maybe even make them more advanced). If there is a feature I left, out leave a comment and I can make the changes. The library is supposed to be just a set of javascript functions, css identifiers, and html tags that work together. If you download the library, nothing will be defined to look like anything at all.

Any questions or comments, feel free to leave them below!