This JavaScript code snippet helps you to create custom audio player controls. It creates an audio player using HTML, CSS, and JavaScript. The first few lines select the audio player element and create an Audio object with a specific URL. When the audio has loaded, the duration is displayed and the volume is set to 75%. The timeline and volume slider elements are set up to respond to user interaction, allowing the user to skip around in the audio and adjust the volume. A progress bar displays the current position in the audio, and the play/pause button toggles between playing and pausing the audio. Additionally, there is a function to convert the duration of the audio from seconds to a formatted timecode.
There are also possible improvements suggested in the comments, including changing the sliders into input sliders and making the player into a Vue or React component.
How to Create JavaScript Audio Player With Custom Controls
First of all, load the following assets into the head tag of your HTML document.
<link rel='stylesheet' href='https://icono-49d6.kxcdn.com/icono.min.css'>
Create the HTML structure for the custom audio player controls as follows:
<audio controls> <source src="https://ia800905.us.archive.org/19/items/FREE_background_music_dhalius/backsound.mp3" type="audio/mp3"> </audio> <div style="width: 50px; height: 50px;"></div> <div class="audio-player"> <div class="timeline"> <div class="progress"></div> </div> <div class="controls"> <div class="play-container"> <div class="toggle-play play"> </div> </div> <div class="time"> <div class="current">0:00</div> <div class="divider">/</div> <div class="length"></div> </div> <div class="name">Music Song</div> <!-- credit for icon to https://saeedalipoor.github.io/icono/ --> <div class="volume-container"> <div class="volume-button"> <div class="volume icono-volumeMedium"></div> </div> <div class="volume-slider"> <div class="volume-percentage"></div> </div> </div> </div> </div>
Now, style the custom audio player controls using the following CSS styles:
body { display: flex; justify-content: center; align-items: center; height: 100vh; overflow: hidden; background: linear-gradient(to bottom right, #b968c5, skyblue); } .audio-player { height: 50px; width: 350px; background: #444; box-shadow: 0 0 20px 0 #000a; font-family: arial; color: white; font-size: 0.75em; overflow: hidden; display: grid; grid-template-rows: 6px auto; } .audio-player .timeline { background: white; width: 100%; position: relative; cursor: pointer; box-shadow: 0 2px 10px 0 #0008; } .audio-player .timeline .progress { background: coral; width: 0%; height: 100%; transition: 0.25s; } .audio-player .controls { display: flex; justify-content: space-between; align-items: stretch; padding: 0 20px; } .audio-player .controls > * { display: flex; justify-content: center; align-items: center; } .audio-player .controls .toggle-play.play { cursor: pointer; position: relative; left: 0; height: 0; width: 0; border: 7px solid #0000; border-left: 13px solid white; } .audio-player .controls .toggle-play.play:hover { transform: scale(1.1); } .audio-player .controls .toggle-play.pause { height: 15px; width: 20px; cursor: pointer; position: relative; } .audio-player .controls .toggle-play.pause:before { position: absolute; top: 0; left: 0px; background: white; content: ""; height: 15px; width: 3px; } .audio-player .controls .toggle-play.pause:after { position: absolute; top: 0; right: 8px; background: white; content: ""; height: 15px; width: 3px; } .audio-player .controls .toggle-play.pause:hover { transform: scale(1.1); } .audio-player .controls .time { display: flex; } .audio-player .controls .time > * { padding: 2px; } .audio-player .controls .volume-container { cursor: pointer; position: relative; z-index: 2; } .audio-player .controls .volume-container .volume-button { height: 26px; display: flex; align-items: center; } .audio-player .controls .volume-container .volume-button .volume { transform: scale(0.7); } .audio-player .controls .volume-container .volume-slider { position: absolute; left: -3px; top: 15px; z-index: -1; width: 0; height: 15px; background: white; box-shadow: 0 0 20px #000a; transition: 0.25s; } .audio-player .controls .volume-container .volume-slider .volume-percentage { background: coral; height: 100%; width: 75%; } .audio-player .controls .volume-container:hover .volume-slider { left: -123px; width: 120px; }
Finally, add the following JavaScript function for its functionality:
// Possible improvements: // - Change timeline and volume slider into input sliders, reskinned // - Change into Vue or React component // - Be able to grab a custom title instead of "Music Song" // - Hover over sliders to see preview of timestamp/volume change const audioPlayer = document.querySelector(".audio-player"); const audio = new Audio( "https://ia800905.us.archive.org/19/items/FREE_background_music_dhalius/backsound.mp3" ); //credit for song: Adrian kreativaweb@gmail.com console.dir(audio); audio.addEventListener( "loadeddata", () => { audioPlayer.querySelector(".time .length").textContent = getTimeCodeFromNum( audio.duration ); audio.volume = .75; }, false ); //click on timeline to skip around const timeline = audioPlayer.querySelector(".timeline"); timeline.addEventListener("click", e => { const timelineWidth = window.getComputedStyle(timeline).width; const timeToSeek = e.offsetX / parseInt(timelineWidth) * audio.duration; audio.currentTime = timeToSeek; }, false); //click volume slider to change volume const volumeSlider = audioPlayer.querySelector(".controls .volume-slider"); volumeSlider.addEventListener('click', e => { const sliderWidth = window.getComputedStyle(volumeSlider).width; const newVolume = e.offsetX / parseInt(sliderWidth); audio.volume = newVolume; audioPlayer.querySelector(".controls .volume-percentage").style.width = newVolume * 100 + '%'; }, false) //check audio percentage and update time accordingly setInterval(() => { const progressBar = audioPlayer.querySelector(".progress"); progressBar.style.width = audio.currentTime / audio.duration * 100 + "%"; audioPlayer.querySelector(".time .current").textContent = getTimeCodeFromNum( audio.currentTime ); }, 500); //toggle between playing and pausing on button click const playBtn = audioPlayer.querySelector(".controls .toggle-play"); playBtn.addEventListener( "click", () => { if (audio.paused) { playBtn.classList.remove("play"); playBtn.classList.add("pause"); audio.play(); } else { playBtn.classList.remove("pause"); playBtn.classList.add("play"); audio.pause(); } }, false ); audioPlayer.querySelector(".volume-button").addEventListener("click", () => { const volumeEl = audioPlayer.querySelector(".volume-container .volume"); audio.muted = !audio.muted; if (audio.muted) { volumeEl.classList.remove("icono-volumeMedium"); volumeEl.classList.add("icono-volumeMute"); } else { volumeEl.classList.add("icono-volumeMedium"); volumeEl.classList.remove("icono-volumeMute"); } }); //turn 128 seconds into 2:08 function getTimeCodeFromNum(num) { let seconds = parseInt(num); let minutes = parseInt(seconds / 60); seconds -= minutes * 60; const hours = parseInt(minutes / 60); minutes -= hours * 60; if (hours === 0) return `${minutes}:${String(seconds % 60).padStart(2, 0)}`; return `${String(hours).padStart(2, 0)}:${minutes}:${String( seconds % 60 ).padStart(2, 0)}`; }
That’s all! hopefully, you have successfully created JavaScript audio player with custom controls. If you have any questions or suggestions, feel free to comment below.