Make A Simple Music and Audio Player Using HTML, CSS and JavaScript
By Bytewebster - August 3, 2022
Welcome to bytewebster blog. In this project, We created a Custom Music Player With the help of HTML, CSS, and JavaScript. which helps you to get hands-on experience with JavaScript concepts and methods.
This music player has several features like repeating or shuffling a song, playing and pausing a song, or playing the next or previous song. And there is a progress bar in the middle of the player.
How It Works:
This is a custom music player created without using the "controls" tag inside the audio tag. this music player can feature a specific song cover picture as long as you turn the music on.
Detailed Overview:
You can make changes in this CSS after downloading the Source Code Files like you can change the colors, background colors, and add other audios or music. you can also add music to play in the "music folder"
HTML Structure
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Music Player By ByteWebster</title>
<link rel="stylesheet" href="style.css">
<!-- www.bytewebster.com -->
<!-- www.bytewebster.com -->
<!-- www.bytewebster.com (Visit) -->
</head>
<body>
<div class="player">
<div class="player__header">
<div class="player__img player__img--absolute slider">
<button class="player__button player__button--absolute--nw playlist">
<img src="http://physical-authority.surge.sh/imgs/icon/playlist.svg" alt="playlist-icon">
</button>
<button class="player__button player__button--absolute--center play">
<img src="http://physical-authority.surge.sh/imgs/icon/play.svg" alt="play-icon">
<img src="http://physical-authority.surge.sh/imgs/icon/pause.svg" alt="pause-icon">
</button>
<div class="slider__content">
<img class="img slider__img" src="https://linkstorage.linkfire.com/medialinks/images/75b3f52c-3825-4f71-9f86-1ba5ede247ff/artwork-440x440.jpg" alt="cover">
<img class="img slider__img" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/451/100x100/imagine-1586953710-4wJybAsS8x.jpg" alt="cover">
<img class="img slider__img" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/434/100x100/linked-1586953317-0BranYHgw8.jpg" alt="cover">
<img class="img slider__img" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/487/100x100/why-do-i-feat-bri-tolani-1586954592-AkIU1vSG9q.jpg" alt="cover">
<img class="img slider__img" src="https://sound.peal.io/ps/covers/000/036/044/large/hqdefault.jpg?1569616162" alt="cover">
<img class="img slider__img" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/143/100x100/heroes-tonight-feat-johnning-1586946923-LsvZKuKHRf.jpg" alt="cover">
<img class="img slider__img" src="https://linkstorage.linkfire.com/medialinks/images/7268dbaf-880f-4b40-aafe-0d45e278fe47/artwork-440x440.jpg" alt="cover">
</div>
</div>
<div class="player__controls">
<button class="player__button back">
<img class="img" src="http://physical-authority.surge.sh/imgs/icon/back.svg" alt="back-icon">
</button>
<p class="player__context slider__context">
<strong class="slider__name"></strong>
<span class="player__title slider__title"></span>
</p>
<button class="player__button next">
<img class="img" src="http://physical-authority.surge.sh/imgs/icon/next.svg" alt="next-icon">
</button>
<div class="progres">
<div class="progres__filled"></div>
</div>
</div>
</div>
<ul class="player__playlist list">
<li class="player__song">
<img class="player__img img" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/286/100x100/make-me-move-feat-karra-1586948717-dTsA9So1cu.jpg" alt="Make Me Move (feat. KARRA)" title="Make Me Move (feat. KARRA)">
<p class="player__context">
<b class="player__song-name">Make Me Move (feat. KARRA)</b>
<span class="flex">
<span class="player__title">Culture Code, KARRA</span>
<span class="player__song-time"></span>
</span>
</p>
<audio class="audio" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/286/make-me-move-feat-karra-1586948725-C9SPOA3UZn.mp3"></audio>
</li>
<li class="player__song">
<img class="player__img img" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/451/100x100/imagine-1586953710-4wJybAsS8x.jpg" alt="cover">
<p class="player__context">
<b class="player__song-name">Imagine</b>
<span class="flex">
<span class="player__title">Jim Yosef</span>
<span class="player__song-time"></span>
</span>
</p>
<audio class="audio" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/451/imagine-1586953712-PjfTAsj2s7.mp3"></audio>
</li>
<li class="player__song">
<img class="player__img img" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/434/100x100/linked-1586953317-0BranYHgw8.jpg" alt="cover">
<p class="player__context">
<b class="player__song-name">Linked</b>
<span class="flex">
<span class="player__title">Jim Yosef, Anna Yvette</span>
<span class="player__song-time"></span>
</span>
</p>
<audio class="audio" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/434/linked-1586953319-v8FLkcjqgO.mp3"></audio>
</li>
<li class="player__song">
<img class="player__img img" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/487/100x100/why-do-i-feat-bri-tolani-1586954592-AkIU1vSG9q.jpg" alt="cover">
<p class="player__context">
<b class="player__song-name">Why Do I? (feat. Bri Tolani)</b>
<span class="flex">
<span class="player__title">Unknown Brain, Bri Tolani</span>
<span class="player__song-time"></span>
</span>
</p>
<audio class="audio" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/487/why-do-i-feat-bri-tolani-1586954600-5IMWlSMhuc.mp3"></audio>
</li>
<li class="player__song">
<img class="player__img img" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/137/100x100/invincible-1586946874-ZUsn5ZwSWh.jpg" alt="cover">
<p class="player__context ">
<b class="player__song-name">Invincible</b>
<span class="flex">
<span class="player__title">DEAF KEV</span>
<span class="player__song-time"></span>
</span>
</p>
<audio class="audio" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/137/invincible-1586946876-v3qvV3TEKb.mp3"></audio>
</li>
<li class="player__song">
<img class="player__img img" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/143/100x100/heroes-tonight-feat-johnning-1586946923-LsvZKuKHRf.jpg" alt="cover">
<p class="player__context">
<b class="player__song-name">Heroes Tonight (feat. Johnning)</b>
<span class="flex">
<span class="player__title">Janji, Johnning</span>
<span class="player__song-time"></span>
</span>
</p>
<audio class="audio" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/000/143/heroes-tonight-feat-johnning-1586946924-fcppiBJp7z.mp3"></audio>
</li>
<li class="player__song">
<img class="player__img img" src="https://linkstorage.linkfire.com/medialinks/images/7268dbaf-880f-4b40-aafe-0d45e278fe47/artwork-440x440.jpg" alt="cover">
<p class="player__context ">
<b class="player__song-name">Collide</b>
<span class="flex">
<span class="player__title">Elektronomia</span>
<span class="player__song-time"></span>
</span>
</p>
<audio class="audio" src="https://ncsmusic.s3.eu-west-1.amazonaws.com/tracks/000/001/081/collide-1643284836-kJ42U7PzET.mp3"></audio>
</li>
</ul>
</div>
<script src="script.js"></script>
</body>
</html>
We have not used jquery and any other javascript library to make this music player In the script.js file there will be an onclick event a JavaScript event that will perform the next and previous-song() functions when buttons are clicked.
Styling With CSS
/*www.bytewebster.com*/
/*www.bytewebster.com*/
/*www.bytewebster.com (Visit)*/
@import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@700&display=swap');
html {
box-sizing: border-box ;
--parent-height : 20em ;
--duration: 1s ;
--duration-text-wrap: 12s 1.5s cubic-bezier(0.82, 0.82, 1, 1.01) ;
--cubic-header: var(--duration) cubic-bezier(0.71, 0.21, 0.3, 0.95) ;
--cubic-slider : var(--duration) cubic-bezier(0.4, 0, 0.2, 1) ;
--cubic-play-list : .35s var(--duration) cubic-bezier(0, 0.85, 0.11, 1.64) ;
--cubic-slider-context : cubic-bezier(1, -0.01, 1, 1.01) ;
}
html *,
html *::before,
html *::after {
box-sizing: inherit ;
scrollbar-width: none ;
}
body{
margin: 0 ;
height: 100vh ;
display: flex ;
user-select: none ;
align-items: center ;
justify-content: center ;
background-color: #282730 ;
font-family: 'Quicksand', sans-serif ;
-webkit-tap-highlight-color: transparent ;
transition: background-color var(--cubic-slider) ;
}
.img {
width: 100% ;
flex-shrink: 0;
display: block ;
object-fit: cover ;
}
.list {
margin: 0 ;
padding: 0 ;
list-style-type: none ;
}
.flex {
display: flex ;
align-items: center ;
justify-content: space-between ;
}
.uppercase{
text-transform: uppercase ;
}
.player {
width: 17.15em ;
display: flex ;
overflow: hidden ;
font-size: 1.22em ;
border-radius: 1.35em ;
flex-direction: column ;
background-color: white ;
height: var(--parent-height) ;
}
.player__header {
z-index: 1 ;
gap: 0 .4em ;
width: 100% ;
display: flex;
height: 5.85em ;
flex-shrink: 0 ;
position: relative;
align-items: flex-start ;
border-radius: inherit ;
justify-content: flex-end ;
background-color: white ;
padding: .95em 0.6em 0 1.2em ;
box-shadow: 0 2px 6px 1px #0000001f ;
transition: height var(--cubic-header), box-shadow var(--duration), padding var(--duration) ease-in-out ;
}
.player__header.open-header {
height: 100% ;
padding-left: 0 ;
padding-right: 0 ;
box-shadow: unset ;
}
.player__img {
width: 3.22em ;
height: 3.22em ;
border-radius: 1.32em ;
}
.player__img--absolute {
top: 1.4em ;
left: 1.2em ;
position: absolute ;
}
.slider {
flex-shrink: 0 ;
overflow: hidden ;
transition: width var(--cubic-header), height var(--cubic-header), top var(--cubic-header), left var(--cubic-header);
}
.slider.open-slider{
top: 0 ;
left: 0 ;
width: 100% ;
height: 14.6em ;
}
.slider__content {
display: flex ;
height: 100% ;
will-change : transform ;
transition: transform var(--cubic-slider);
}
.slider__img {
filter: brightness(75%) ;
}
.slider__name,
.slider__title {
overflow: hidden ;
white-space: nowrap ;
}
.text-wrap {
display: block ;
white-space: pre ;
width: fit-content ;
animation: text-wrap var(--duration-text-wrap) infinite ;
}
@keyframes text-wrap {
75%{
transform: translate3d(-51.5%, 0, 0) ;
}
100%{
transform: translate3d(-51.5%, 0, 0) ;
}
}
.player__button {
all: unset ;
z-index: 100 ;
width: 2.5em ;
height: 2.5em ;
cursor: pointer ;
}
.playlist {
transform: scale(0) ;
transition: transform calc(var(--duration) / 2) ;
}
.slider.open-slider .playlist {
transform: scale(1) ;
transition: transform var(--cubic-play-list) ;
}
.player__button--absolute--nw {
top: 5.5% ;
left: 5.5% ;
position: absolute ;
}
.player__button--absolute--center {
top: 0 ;
left: 0 ;
right: 0 ;
bottom: 0 ;
margin: auto ;
position: absolute ;
}
img[alt ="pause-icon"] {
display: none ;
}
.player__controls {
width: 77% ;
gap: .5em 0 ;
display: flex ;
flex-wrap: wrap ;
align-items: center ;
will-change: contents ;
align-content: center ;
justify-content: center ;
transition: transform var(--cubic-header) , width var(--cubic-header) ;
}
.player__controls.move {
width: 88% ;
transform: translate3d(-1.1em , calc(var(--parent-height) - 153%) , 0) ;
}
.player__context {
margin: 0 ;
width: 100% ;
display: flex ;
line-height: 1.8 ;
flex-direction: column ;
justify-content: center ;
text-transform: capitalize ;
}
.slider__context {
width: 56.28% ;
cursor: pointer ;
text-align: center ;
padding-bottom: .2em ;
will-change: contents ;
transition: width var(--cubic-header) ;
animation: calc(var(--duration) / 2) var(--cubic-slider-context) ;
}
@keyframes opacity {
0% {
opacity: 0 ;
}
90%{
opacity: 1 ;
}
}
.player__controls.move .slider__context{
width: 49.48% ;
}
.player__title {
font-size: .7em ;
font-weight: bold ;
color: #00000086 ;
}
.progres {
width: 90% ;
height: .25em ;
cursor: pointer ;
border-radius: 1em ;
touch-action : none ;
background-color: #e5e7ea ;
transition: width var(--cubic-header) ;
}
.player__controls.move .progres{
width: 98% ;
}
.progres__filled {
width: 0% ;
height: 100% ;
display: flex ;
position: relative ;
align-items: center ;
border-radius: inherit ;
background-color: #78adfe ;
}
.progres__filled::before {
right: 0 ;
width: .35em ;
content: " " ;
height: .35em ;
border-radius: 50% ;
position: absolute ;
background-color: #5781bd ;
}
.player__playlist {
height: 100% ;
overflow: auto ;
padding: 1.05em .9em 0 1.2em ;
}
.player__playlist::-webkit-scrollbar {
width: 0 ;
}
.player__song {
/* gap: 0 .65em ; */
display: flex ;
cursor: pointer ;
margin-bottom: .5em ;
padding-bottom: .7em ;
border-bottom: .1em solid #d8d8d859 ;
}
.player__song .player__context {
line-height: 1.5 ;
margin-left: .65em ;
}
.player__song-name {
font-size: .88em ;
}
.player__song-time {
font-size: .65em ;
font-weight: bold ;
color: #00000079 ;
height: fit-content ;
align-self: flex-end ;
}
.audio {
display: none !important ;
}
When the Play or pause button is clicked, the HTML element will run a function in the .js file, the logic in the IF statement will be executed, and the playing variable will be set to false.
To insert music and images, you have to: 1: Place image(jpg) on images folder and music(mp3) on music folder CAREFULL Images and audio must have the same name 2: Write song's name on javascript's song array
Script Overview
// Designed by: Mauricio Bucardo
// Original image: https://dribbble.com/shots/6957353-Music-Player-Widget
"use strict";
// add elemnts
const bgBody = ["#282730", "#a0e0ba", "#56ce67", "#f3f4f8", "#778b9b", "#ffcbdc", "#7f9fdc"];
const body = document.body;
const player = document.querySelector(".player");
const playerHeader = player.querySelector(".player__header");
const playerControls = player.querySelector(".player__controls");
const playerPlayList = player.querySelectorAll(".player__song");
const playerSongs = player.querySelectorAll(".audio");
const playButton = player.querySelector(".play");
const nextButton = player.querySelector(".next");
const backButton = player.querySelector(".back");
const playlistButton = player.querySelector(".playlist");
const slider = player.querySelector(".slider");
const sliderContext = player.querySelector(".slider__context");
const sliderName = sliderContext.querySelector(".slider__name");
const sliderTitle = sliderContext.querySelector(".slider__title");
const sliderContent = slider.querySelector(".slider__content");
const sliderContentLength = playerPlayList.length - 1;
const sliderWidth = 100;
let left = 0;
let count = 0;
let song = playerSongs[count];
let isPlay = false;
const pauseIcon = playButton.querySelector("img[alt = 'pause-icon']");
const playIcon = playButton.querySelector("img[alt = 'play-icon']");
const progres = player.querySelector(".progres");
const progresFilled = progres.querySelector(".progres__filled");
let isMove = false;
// creat functions
function openPlayer() {
playerHeader.classList.add("open-header");
playerControls.classList.add("move");
slider.classList.add("open-slider");
}
function closePlayer() {
playerHeader.classList.remove("open-header");
playerControls.classList.remove("move");
slider.classList.remove("open-slider");
}
function next(index) {
count = index || count;
if (count == sliderContentLength) {
count = count;
return;
}
left = (count + 1) * sliderWidth;
left = Math.min(left, (sliderContentLength) * sliderWidth);
sliderContent.style.transform = `translate3d(-${left}%, 0, 0)`;
count++;
run();
}
function back(index) {
count = index || count;
if (count == 0) {
count = count;
return;
}
left = (count - 1) * sliderWidth;
left = Math.max(0, left);
sliderContent.style.transform = `translate3d(-${left}%, 0, 0)`;
count--;
run();
}
function changeSliderContext() {
sliderContext.style.animationName = "opacity";
sliderName.textContent = playerPlayList[count].querySelector(".player__title").textContent;
sliderTitle.textContent = playerPlayList[count].querySelector(".player__song-name").textContent;
if (sliderName.textContent.length > 16) {
const textWrap = document.createElement("span");
textWrap.className = "text-wrap";
textWrap.innerHTML = sliderName.textContent + " " + sliderName.textContent;
sliderName.innerHTML = "";
sliderName.append(textWrap);
}
if (sliderTitle.textContent.length >= 18) {
const textWrap = document.createElement("span");
textWrap.className = "text-wrap";
textWrap.innerHTML = sliderTitle.textContent + " " + sliderTitle.textContent;
sliderTitle.innerHTML = "";
sliderTitle.append(textWrap);
}
}
function changeBgBody() {
body.style.backgroundColor = bgBody[count];
}
function selectSong() {
song = playerSongs[count];
for (const item of playerSongs) {
if (item != song) {
item.pause();
item.currentTime = 0;
}
}
if (isPlay) song.play();
}
function run() {
changeSliderContext();
changeBgBody();
selectSong();
}
function playSong() {
if (song.paused) {
song.play();
playIcon.style.display = "none";
pauseIcon.style.display = "block";
}else{
song.pause();
isPlay = false;
playIcon.style.display = "";
pauseIcon.style.display = "";
}
}
function progresUpdate() {
const progresFilledWidth = (this.currentTime / this.duration) * 100 + "%";
progresFilled.style.width = progresFilledWidth;
if (isPlay && this.duration == this.currentTime) {
next();
}
if (count == sliderContentLength && song.currentTime == song.duration) {
playIcon.style.display = "block";
pauseIcon.style.display = "";
isPlay = false;
}
}
function scurb(e) {
// If we use e.offsetX, we have trouble setting the song time, when the mousemove is running
const currentTime = ( (e.clientX - progres.getBoundingClientRect().left) / progres.offsetWidth ) * song.duration;
song.currentTime = currentTime;
}
function durationSongs() {
let min = parseInt(this.duration / 60);
if (min < 10) min = "0" + min;
let sec = parseInt(this.duration % 60);
if (sec < 10) sec = "0" + sec;
const playerSongTime = `${min}:${sec}`;
this.closest(".player__song").querySelector(".player__song-time").append(playerSongTime);
}
changeSliderContext();
// add events
sliderContext.addEventListener("click", openPlayer);
sliderContext.addEventListener("animationend", () => sliderContext.style.animationName ='');
playlistButton.addEventListener("click", closePlayer);
nextButton.addEventListener("click", () => {
next(0)
});
backButton.addEventListener("click", () => {
back(0)
});
playButton.addEventListener("click", () => {
isPlay = true;
playSong();
});
playerSongs.forEach(song => {
song.addEventListener("loadeddata" , durationSongs);
song.addEventListener("timeupdate" , progresUpdate);
});
progres.addEventListener("pointerdown", (e) => {
scurb(e);
isMove = true;
});
document.addEventListener("pointermove", (e) => {
if (isMove) {
scurb(e);
song.muted = true;
}
});
document.addEventListener("pointerup", () => {
isMove = false;
song.muted = false;
});
playerPlayList.forEach((item, index) => {
item.addEventListener("click", function() {
if (index > count) {
next(index - 1);
return;
}
if (index < count) {
back(index + 1);
return;
}
});
});
In Future blog posts, we are also going to set up and build music player applications using react.js from absolutely scratch.
JavaScript Music/Audio Player [Source Codes]
From here You can download the source code files of this JavaScript Music/Audio Player
If you are just starting in web development, these snippets will be useful. We would appreciate it if you would share our posts with other like-minded people.
Video of the project:
Take This Short Survey!
ByteWebster Play and Win Offer.
PLAY A SIMPLE GAME AND WIN PREMIUM WEB DESIGNS WORTH UPTO $100 FOR FREE.
PLAY FOR FREEConnect With Us
we would like to keep in touch with you..... Register Here.