14

How to create Music player with pure HTML, CSS, JS

 2 years ago
source link: https://dev.to/kunaal438/how-to-create-music-player-with-pure-html-css-js-c1j
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Hello, Today we'll see, how we can easily create a music player using HTML, CSS and JS only. No other library. Our music player has modern looking designs, with cool animations like play/pause animation, disk rotating animation and pulse animation. Our music player has working forward/backward buttons with seek-able song slider.

To see demo or you want full coding tutorial video for better understanding. You can watch the tutorial below.

Video Tutorial

I appreciate if you can support me by subscribing my youtube channel.

Before we start writing our code. Although it's not a Nodejs app but we should see its folder structure at least.

So, now let's start designing our music player.

First, of course write basic HTML template inside index.html file and link style.css, app.js to it. Then make a music player container.

<div class="music-player">
</div>
Enter fullscreen modeExit fullscreen mode
*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body{
    width: 100%;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #5f7a61;
    font-family: 'roboto', sans-serif;
}

.music-player{
    width: 350px;
    height: 550px;
    border-radius: 20px;
    background: rgba(255, 255, 255, 0.08);
    box-shadow: 0 40px 100px rgba(255, 255, 255, 0.1);
    padding: 30px;
    overflow: hidden;
    color: #d5eebb;
}
Enter fullscreen modeExit fullscreen mode

Output

Now make song name, artist name.

<!-- Inside music player element -->
<h1 class="music-name">song one</h1>
<p class="artist-name">artist</p>
Enter fullscreen modeExit fullscreen mode

And of course style them.

.music-name,
.artist-name{
    text-align: center;
    text-transform: capitalize;
}

.music-name{
    font-size: 40px;
    font-weight: 500;
    margin-bottom: 10px;
}

.artist-name{
    font-size: 20px;
}
Enter fullscreen modeExit fullscreen mode

here " , " (comma) is used to give same style to more than one element.

Output

Great! Now make disk/cover image of the song. For that we use just a single div and will give background-image to set song cover image.

<div class="disk"></div>
Enter fullscreen modeExit fullscreen mode

Remember all the elements we are adding inside music player container.

.disk{
    position: relative;
    display: block;
    margin: 40px auto;
    width: 180px;
    height: 180px;
    border-radius: 50%;
    background-image: url('images/cover\ 1.png');
    background-size: cover;
    box-shadow: 0 0 0 10px rgba(255, 255, 255, 0.08);
}
Enter fullscreen modeExit fullscreen mode

here, I am using box-shadow to create outer circle for the disk.

Output

But, how we make a hole at the center. For that, we'll use ::before pseudo element. You can find more about it here.

.disk::before{
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: #5f7a61;
}
Enter fullscreen modeExit fullscreen mode

Output

Hmm! It looking great. Now, make seek bar for the music player of course.

<div class="song-slider">
    <input type="range" value="0" class="seek-bar">
</div>
Enter fullscreen modeExit fullscreen mode
.song-slider{
    width: 100%;
    position: relative;
}

.seek-bar{
    -webkit-appearance: none;
    width: 100%;
    height: 5px;
    border-radius: 10px;
    background: #7fc8a9;
    overflow: hidden;
    cursor: pointer;
}

.seek-bar::-webkit-slider-thumb{
    -webkit-appearance: none;
    width: 1px;
    height: 20px;
    box-shadow: -400px 0 0 400px #d5eebb;
}
Enter fullscreen modeExit fullscreen mode
  1. -webkit-appearance : this is used to hide all the default styles of the element done by browser.
  2. -webkit-slider-thumb : this will select the thumb or head of the slider, that we drag.

Output

Make music current time and duration element now.

<div class="song-slider">
    <input type="range" value="0" class="seek-bar">
    <span class="current-time">00:00</span>
    <span class="song-duration">00:00</span>
</div>
Enter fullscreen modeExit fullscreen mode
.current-time,
.song-duration{
    font-size: 14px;
}

.song-duration{
    position: absolute;
    right: 0;
}
Enter fullscreen modeExit fullscreen mode

Output

Now, make controls. We'll make play button icon with CSS and forward/backward button will be the images.

<div class="controls">
    <button class="play-btn">
        <span></span>
        <span></span>
    </button>
</div>
Enter fullscreen modeExit fullscreen mode
.controls{
    width: 60%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin: auto;
    margin-top: 20px;
}

.play-btn{
    position: relative;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background: #d5eebb;
    cursor: pointer;
    border: none;
}

.play-btn span{
    position: absolute;
    top: 50%;
    left: 25%;
    transform: translateY(-50%);
    width: 10px;
    height: 30px;
    border-radius: 2px;
    background: #5f7a61;
    transition: .5s;
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%);
}

.play-btn span:nth-child(2){
    left: 55%;
    transform-origin: center;
}
Enter fullscreen modeExit fullscreen mode

If you notice here, in the span selector, I am setting default clip-path, this is because I want smooth transition when using clip-path for that I need to define a default value as well. And the the value of clip path is just a rectangle.

Output

Now I want to make this pause logo to a play logo. For that I'll use an extra class pause.

.play-btn.pause span:nth-child(2){
    transform: translateY(-50%) scaleY(0);
}

.play-btn.pause span:nth-child(1){
    width: 35%;
    left: 53%;
    transform: translate(-50%, -50%);
    border-radius: 0;
    clip-path: polygon(0 0, 100% 50%, 100% 50%, 0% 100%);
}
Enter fullscreen modeExit fullscreen mode
  1. When you have some thing like this .class.class or .class#id or #id.class have multiple selector without space. This means you are selecting the elements when having both classes/ids.

  2. What we did in the above CSS is, when the play icon have pause class, we are scaling down its 2nd span to 0 making it fully disappear. And using clip-path to make a triangle shape for the first span.

Output

Output when toggling the play-btn element's pause class from chrome inspector.

Now make pulse animation and add it to play-btn when having pause class.

.play-btn.pause{
    animation: pulse 2s linear infinite;
}

@keyframes pulse{
    0%{
        box-shadow: 0;
    }
    50%{
        box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.1);
    }
    100%{
        box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.4);
    }
}
Enter fullscreen modeExit fullscreen mode

Add pause class to the play-btn element as default. Great! Now make forward/backward buttons.

<div class="controls">
    <button class="btn backward-btn"><img src="images/pre.png" alt=""></button>
    <button class="play-btn pause">
        <span></span>
        <span></span>
    </button>
    <button class="btn forward-btn"><img src="images/nxt.png" alt=""></button>
</div> 
Enter fullscreen modeExit fullscreen mode
.btn{
    width: 40px;
    height: 40px;
    background: #d5eebb;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    border: none;
    cursor: pointer;
}
Enter fullscreen modeExit fullscreen mode

Output

Now the last animation we want is disk rotation. For that make an animation.

@keyframes rotate{
    0%{
        transform: rotate(0);
    }
    100%{
        transform: rotate(360deg);
    }
}
Enter fullscreen modeExit fullscreen mode

But how to give this animation. Give this animation as default to .disk element. But set its animation-play-state to paused. animation-play-state is used to set animation state. In this case we want animation to be paused at start.

And change the state to running, when disk element have class play.

.disk{
    // previous styles
    animation: rotate 20s linear infinite;
    animation-play-state: paused;
}

.disk.play{
    animation-play-state: running;
}
Enter fullscreen modeExit fullscreen mode

We are done with designing the player. Now, let's make this player function.

Before writing JS, make sure you do these things.

  1. Make an audio source. We of course need an audio source to play the music. For that just make an empty audio element at the very start and give it a id so we can access it in JS.
<audio src="" id="audio"></audio>
Enter fullscreen modeExit fullscreen mode
  1. And 2nd thing is, make sure you add data.js file before app.js because, our data is in data.js but we can only access it in app.js if we import it before app.js.

Now we can write JS.

Initialize a variable to store current music index. Set it default value to 0.

let currentMusic = 0;
Enter fullscreen modeExit fullscreen mode

Now select each and every element that we need to add some behaviour.

const music = document.querySelector('#audio');

const seekBar = document.querySelector('.seek-bar');
const songName = document.querySelector('.music-name');
const artistName = document.querySelector('.artist-name');
const disk = document.querySelector('.disk');
const currentTime = document.querySelector('.current-time');
const musicDuration = document.querySelector('.song-duration');
const playBtn = document.querySelector('.play-btn');
const forwardBtn = document.querySelector('.forward-btn');
const backwardBtn = document.querySelector('.backward-btn');
Enter fullscreen modeExit fullscreen mode

Once you are done selecting all the elements. make a function to setup the music.

// setup music

const setMusic = (i) => {
    seekBar.value = 0; // set range slide value to 0;
    let song = songs[i];
    currentMusic = i;
    music.src = song.path;

    songName.innerHTML = song.name;
    artistName.innerHTML = song.artist;
    disk.style.backgroundImage = `url('${song.cover}')`;

    currentTime.innerHTML = '00:00';
    setTimeout(() => {
        seekBar.max = music.duration;
        musicDuration.innerHTML = formatTime(music.duration);
    }, 300);
}
Enter fullscreen modeExit fullscreen mode

Here, we are setting up the song. Thing to notice here is,

  1. setTimeout - I am using this because, there is a slight time difference in setting up the music and accessing it. Which causing an error while accessing its duration.
  2. formatTime - This is a function that we'll create next. This function will take time as an argument, and return us the formatted value. For instance is we pass - formatTime(120) then it will return 02:00.

Don't forget to call the setMusic once with 0 as an argument.

setMusic(0);
Enter fullscreen modeExit fullscreen mode

Create format time function.

// formatting time in min and seconds format

const formatTime = (time) => {
    let min = Math.floor(time / 60);
    if(min < 10){
        min = `0${min}`;
    }
    let sec = Math.floor(time % 60);
    if(sec < 10){
        sec = `0${sec}`;
    }
    return `${min} : ${sec}`;
}
Enter fullscreen modeExit fullscreen mode

Now we can add click event to our play button.

playBtn.addEventListener('click', () => {
    if(playBtn.className.includes('pause')){
        music.play();
    } else{
        music.pause();
    }
    playBtn.classList.toggle('pause');
    disk.classList.toggle('play');
})
Enter fullscreen modeExit fullscreen mode

element.className returns its classes and includes method is used to find a particular string is inside the text or not.

Now make seek bar update to song's current time after every 500ms.

// seek bar
setInterval(() => {
    seekBar.value = music.currentTime;
    currentTime.innerHTML = formatTime(music.currentTime);
}, 500)
Enter fullscreen modeExit fullscreen mode

This will update the seek bar after every 500ms.
Now, we also want to jump in between song time. For that add change event to the seek bar.

seekBar.addEventListener('change', () => {
    music.currentTime = seekBar.value;
})
Enter fullscreen modeExit fullscreen mode

We are almost done. Now create forward/backward click events.

// forward and backward button
forwardBtn.addEventListener('click', () => {
    if(currentMusic >= songs.length - 1){
        currentMusic = 0;
    } else{
        currentMusic++;
    }
    setMusic(currentMusic);
    playMusic();
})

backwardBtn.addEventListener('click', () => {
    if(currentMusic <= 0){
        currentMusic = songs.length - 1;
    } else{
        currentMusic--;
    }
    setMusic(currentMusic);
    playMusic();
})
Enter fullscreen modeExit fullscreen mode

And yes, if you see we have playMusic function. Its purpose in life is to play music every time.

const playMusic = () => {
    music.play();
    playBtn.classList.remove('pause');
    disk.classList.add('play');
}
Enter fullscreen modeExit fullscreen mode

And the last thing, to make song forward when the current song end. Code this inside 500ms interval.

setInterval(() => {
    seekBar.value = music.currentTime;
    currentTime.innerHTML = formatTime(music.currentTime);
    if(Math.floor(music.currentTime) == Math.floor(seekBar.max)){
        forwardBtn.click();
    }
}, 500)
Enter fullscreen modeExit fullscreen mode

And that's it. Great Job! we are done with our music player. I hope you understood each and everything. If you have doubt or I missed something let me know in the comments.

Articles you may find Useful

I really appreciate if you can subscribe my youtube channel. I create awesome web contents.

Download the assets, Source Code, Donate me on Paypal

My next upcoming tutorials which you might don't want to miss.

  1. Fully working e-commerce website - Fullstack
  2. Responsive Personal Portfolio
  3. Visiting card designer with download feature.

Your donation really motivates me to do more amazing tutorials like this. Support me on patreon, Buy me a coffee, Donate me on paypal

Thanks For reading.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK