Creating a basic music player using HTML, CSS, and JavaScript involves setting up the HTML structure, styling it with CSS, and using JavaScript to handle the playback functionality. Here’s a simple example to get you started:
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Music Player</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.2/font/bootstrap-icons.min.css" /> <link rel="stylesheet" href="style.css" /> </head> <body> <div class="player"> <div class="header"> <button class="menu"> <i class="bi bi-grid-fill"></i> </button> <strong>Now Playing</strong> <button class="show"> <i class="bi bi-music-note-list"></i> </button> </div> <div class="track-info"> <img src="https://placehold.co/200" alt="" class="artwork" /> <h2 class="name"></h2> <h3 class="artist"></h3> <audio id="audio-player"></audio> </div> <div class="seek-slider"> <input type="range" min="1" max="100" value="0" step="0.01" /> <span class="current-time">0:00</span> <span class="duration">0:00</span> </div> <div class="audio-controls"> <button class="prev"> <i class="bi bi-skip-start-fill"></i> </button> <button class="play-pause paused"> <i class="bi bi-play-circle-fill"></i> </button> <button class="next"> <i class="bi bi-skip-end-fill"></i> </button> </div> <div class="volume-slider"> <i class="bi bi-volume-off-fill"></i> <input type="range" min="1" max="100" /> <i class="bi bi-volume-up-fill"></i> </div> <div class="playlist"> <div class="playlist-header"> <button class="hide"> <i class="bi bi-chevron-right"></i> </button> <strong>My PlayList</strong> </div> <div class="playlist-content"></div> </div> </div> <script src="tracks.js"></script> <script src="script.js"></script> </body> </html>
CSS (styles.css)
@import url("https://fonts.googleapis.com/css2?family=Gabarito:wght@400;500;600&display=swap"); :root { --main-color: #885a89; --dark-color: #363537; --light-color: #fff; --gray-color: #efefef; --width: 320px; } * { padding: 0; margin: 0; box-sizing: border-box; font-family: "Gabarito", sans-serif; } body { min-height: 100svh; display: grid; place-items: center; background-color: var(--main-color); color: var(--dark-color); } button { border: none; cursor: pointer; background-color: transparent; color: var(--dark-color); } button:active, button:hover { color: var(--main-color); } input { appearance: none; background-color: var(--gray-color); outline: none; cursor: pointer; overflow: hidden; width: 100%; } /* firefox */ input::-moz-range-thumb { appearance: none; width: 0; height: 0; box-shadow: calc(-1 * var(--width)) 0 0 var(--width) var(--main-color); } /* webkit */ input::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 0; height: 0; box-shadow: calc(-1 * var(--width)) 0 0 var(--width) var(--main-color); } .player { background-color: var(--light-color); width: 90%; max-width: var(--width); padding: 20px; border-radius: 10px; display: grid; gap: 20px; box-shadow: 0 5px 10px rgba(0, 0, 0, 0.25); position: relative; overflow: hidden; } .header { display: flex; align-items: center; justify-content: space-between; font-size: 1.25rem; } .header .bi { font-size: 1.25rem; } .track-info { text-align: center; } .track-info img { width: 200px; height: 200px; border-radius: 5px; box-shadow: 0 3px 5px rgba(0, 0, 0, 0.15); } .track-info .name { font-size: 1.25rem; font-weight: 500; color: var(--main-color); margin-block: 20px 5px; } .track-info .artist { font-size: 1rem; font-weight: 500; } .seek-slider { display: flex; justify-content: space-between; flex-wrap: wrap; } .seek-slider input { height: 6px; border-radius: 6px; } .seek-slider span { padding: 5px 0; user-select: none; } .audio-controls { display: flex; align-items: center; justify-content: center; gap: 20px; } .audio-controls button { width: 48px; height: 48px; font-size: 3rem; line-height: 1; display: flex; align-items: center; justify-content: center; } .play-pause.paused .bi::before { content: "\F4F2"; } .play-pause:not(.paused) .bi::before { content: "\F4C1"; } .volume-slider { display: flex; align-items: center; justify-content: space-between; gap: 10px; } .volume-slider input { height: 3px; } .volume-slider .bi { font-size: 1.25rem; } .playlist { position: absolute; inset: 0; background-color: var(--light-color); padding: 20px; display: grid; align-content: start; gap: 20px; border: 1px solid var(--gray-color); transform: translateX(100%); transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1); } .playlist.show { transform: none; } .playlist-header { position: relative; text-align: center; font-size: 1.25rem; } .playlist-header button { font-size: 1.25rem; position: absolute; left: 0; top: 50%; transform: translateY(-50%); } .playlist-content { overflow: hidden auto; } .item { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px; cursor: pointer; } .item:not(:last-child) { border-bottom: 1px solid var(--gray-color); } .item.active, .item:hover { background-color: var(--gray-color); } .item:not(.active)::after { content: ""; width: 24px; height: 24px; } .item img { width: 48px; height: 48px; border-radius: 3px; } .item div { flex: 1; } .item h4 { font-size: 1rem; color: var(--main-color); } .item p { font-size: 0.85rem; } .item button { width: 24px; height: 24px; line-height: 1; font-size: 1.5rem; display: flex; align-items: center; justify-content: center; }
JavaScript (script.js)
//* state const state = { activeTrack: 0, initPlay: false }; //* selectors const audio = document.getElementById("audio-player"); const ui = { // sliders seekBar: document.querySelector(".seek-slider input"), volumeBar: document.querySelector(".volume-slider input"), // buttons showPlayListBtn: document.querySelector(".show"), hidePlayListBtn: document.querySelector(".hide"), prevBtn: document.querySelector(".prev"), nextBtn: document.querySelector(".next"), playPauseBtn: document.querySelector(".play-pause"), // text and image playList: document.querySelector(".playlist"), playListContent: document.querySelector(".playlist-content"), artwork: document.querySelector(".artwork"), trackName: document.querySelector(".name"), artist: document.querySelector(".artist"), currentTime: document.querySelector(".current-time"), duration: document.querySelector(".duration"), }; //* event listeners const setupEventListeners = () => { document.addEventListener("DOMContentLoaded", loadTrack); // player events ui.playPauseBtn.addEventListener("click", playPauseTrack); ui.seekBar.addEventListener("input", updateSeek); ui.volumeBar.addEventListener("input", updateVolume); ui.nextBtn.addEventListener("click", nextTrack); ui.prevBtn.addEventListener("click", prevTrack); ui.showPlayListBtn.addEventListener("click", showPlayList); ui.hidePlayListBtn.addEventListener("click", hidePlayList); // audio events audio.addEventListener("ended", nextTrack); audio.addEventListener("timeupdate", updateTime); audio.addEventListener("loadedmetadata", updateTrackInfo); audio.addEventListener("durationchange", updateDuration); }; //* event handlers const updateVolume = () => { audio.volume = ui.volumeBar.value / 100; }; const updateSeek = () => { audio.currentTime = (ui.seekBar.value / 100) * audio.duration; }; const updateTime = () => { ui.seekBar.value = (audio.currentTime / audio.duration) * 100; ui.currentTime.textContent = formatTime(audio.currentTime); }; const updateDuration = () => { ui.seekBar.value = 0; ui.duration.textContent = formatTime(audio.duration); }; const updateTrackInfo = () => { ui.artwork.src = tracks[state.activeTrack].artwork; ui.trackName.textContent = tracks[state.activeTrack].name; ui.artist.textContent = tracks[state.activeTrack].artist; }; const playPauseTrack = () => { audio.paused ? audio.play() : audio.pause(); ui.playPauseBtn.classList.toggle("paused", audio.paused); if (!state.initPlay) state.initPlay = true; renderPlayList(); }; const prevTrack = () => { state.activeTrack = (state.activeTrack - 1 + tracks.length) % tracks.length; loadTrack(); }; const nextTrack = () => { state.activeTrack = (state.activeTrack + 1) % tracks.length; loadTrack(); }; const playTrack = (index) => { if (index === state.activeTrack) { playPauseTrack(); } else { state.activeTrack = index; loadTrack(); } }; const loadTrack = () => { audio.src = tracks[state.activeTrack].path; state.initPlay ? playPauseTrack() : renderPlayList(); }; const formatTime = (time) => { const minutes = Math.floor(time / 60); const seconds = Math.floor(time % 60); return `${minutes}:${seconds.toString().padStart(2, "0")}`; }; const showPlayList = () => { ui.playList.classList.add("show"); }; const hidePlayList = () => { ui.playList.classList.remove("show"); }; const renderPlayList = () => { ui.playListContent.innerHTML = ""; tracks.forEach((track, index) => { const isActive = index === state.activeTrack; const icon = audio.paused ? "bi-play-fill" : "bi-pause-fill"; const item = document.createElement("div"); item.classList.add("item"); item.classList.toggle("active", isActive); item.addEventListener("click", () => playTrack(index)); item.innerHTML = ` <img src="${track.artwork}" alt="${track.name}" /> <div class="item-detail"> <h4>${track.name}</h4> <p>${track.artist}</p> </div> ${isActive ? `<button><i class="bi ${icon}"></i></button>` : ""}`; ui.playListContent.appendChild(item); }); }; renderPlayList(); setupEventListeners();
Track .js
//* Track Source: PixaBay const tracks = [ { artwork: "https://cdn.pixabay.com/audio/2022/05/27/23-46-21-714_200x200.jpg", name: "Best Time", artist: "FAS Sounds", path: "./media/112194.mp3", }, { artwork: "https://cdn.pixabay.com/audio/2023/10/24/15-08-22-671_200x200.jpg", name: "Drive Breakbeat", artist: "Rockot", path: "./media/173062.mp3", }, { artwork: "https://cdn.pixabay.com/audio/2023/07/22/02-53-18-138_200x200.jpg", name: "Tokyo Cafe", artist: "TVARI", path: "./media/159065.mp3", }, { artwork: "https://cdn.pixabay.com/audio/2023/03/19/12-27-22-207_200x200.jpg", name: "Smoke", artist: "Soul Prod Music", path: "./media/143172.mp3", }, { artwork: "https://cdn.pixabay.com/audio/2022/04/13/11-20-13-185_200x200.jpg", name: "Electronic Rock", artist: "Alex Grohl", path: "./media/15045.mp3", }, ];
Explanation
- HTML:
- A basic structure for the music player, including audio controls, play/pause and stop buttons, and a progress bar.
- CSS:
- Basic styling for the music player, buttons, and progress bar.
- JavaScript:
- Event listeners for play/pause and stop buttons.
timeupdate
event listener to update the progress bar and time display.- Input listener on the progress bar to allow seeking within the audio.
loadedmetadata
event listener to set the duration of the audio once it’s loaded.
Replace "path/to/your/music/file.mp3"
with the actual path to your audio file. This basic example can be expanded with additional features such as playlists, volume control, and more advanced styling.
Reviews
There are no reviews yet. Be the first one to write one.