July 01, 2025 • 5 min read
🎧 Building a Neumorphic Music Player with Playlist & Navigation Using HTML, CSS & JavaScript
A stylish Neumorphism-based music player built with HTML, CSS, and JavaScript. Features include playlist navigation, play/pause, next/prev, volume cycling, and a responsive UI with smooth transitions.
A sleek, modern music player with Neumorphism UI, featuring:
- Play/pause, next/prev controls
- Volume cycling button (🔈 to 🔊 to 🔇)
- Playlist screen with clickable songs
- Smooth screen transitions between Playlist and Player
🗂️ Project Structure
music-player/
│
├── index.html
├── style.css
├── script.js
├── cover.jpg
└── music.mp3
🧩 HTML Code for Random Color Generator
The HTML file contains the main structure of the page, including the color display, dropdown, and buttons.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Neumorphic Music Player</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="player-container">
<!-- ✅ Now Playing Screen -->
<div id="nowPlayingScreen" class="screen active">
<div class="header">
<button id="backToPlaylist" class="neumorphic">←</button>
<h2 class="nowPlaying">Now Playing</h2>
<button id="volumeCycleBtn" class="neumorphic">🔊</button>
</div>
<div class="cover">
<img id="cover" src="cover1.jpg" alt="Album Cover" />
</div>
<h2 id="title"></h2>
<h3 id="artist"></h3>
<div class="progress-container">
<span id="current-time">0:00</span>
<input type="range" id="progress" value="0" />
<span id="duration">0:00</span>
</div>
<audio id="audio" src="music1.mp3"></audio>
<div class="controls">
<button id="prev" class="neumorphic"><span>◀◀</span></button>
<button id="play" class="neumorphic play"><span class="play-icon">▶</span></button>
<button id="next" class="neumorphic"><span>▶▶</span></button>
</div>
</div>
<!-- ✅ Playlist Screen -->
<div id="playlistScreen" class="screen">
<div class="header">
<h2>Playlist</h2>
<button id="goToPlayer" class="neumorphic">→</button>
</div>
<ul id="playlist"></ul>
</div>
</div> <!-- END of .player-container -->
<script src="script.js"></script>
</body>
</html>
🌈 CSS Code: Styling the Neumorphism Look
body {
background: #1e1e2f;
font-family: 'Segoe UI', sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: #f0f0f0;
}
.player-container {
background: #2a2a3b;
box-shadow: 10px 10px 20px #181820, -10px -10px 20px #3a3a4f;
border-radius: 30px;
padding: 30px;
width: 300px;
text-align: center;
}
.cover img {
width: 100%;
border-radius: 20px;
box-shadow: inset 6px 6px 12px #1e1e2a, inset -6px -6px 12px #3a3a4f;
}
h2, h3 {
margin: 15px 0 5px;
color: #ffffff;
text-align: center;
}
.controls {
display: flex;
justify-content: space-around;
margin: 20px 0;
}
.neumorphic {
background: #2a2a3b;
border: none;
padding: 15px;
border-radius: 20%;
box-shadow: 6px 6px 12px #181820, -6px -6px 12px #3a3a4f;
cursor: pointer;
font-size: 18px;
color: #ffffff;
}
.neumorphic span {
font-style: normal;
}
.neumorphic:active {
box-shadow: inset 4px 4px 8px #181820, inset -4px -4px 8px #3a3a4f;
}
.progress-container {
display: flex;
align-items: center;
gap: 8px;
margin: 20px 0 30px 0;
}
#progress {
flex: 1;
-webkit-appearance: none;
height: 6px;
border-radius: 4px;
transition: background-size 0.1s linear;
outline: none;
}
#progress::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: #ffffff;
cursor: pointer;
box-shadow: 0 0 5px rgba(255, 255, 255, 0.6);
border: none;
margin-top: -3px; /* aligns it vertically with the bar */
}
#progress::-moz-range-thumb {
width: 12px;
height: 12px;
border-radius: 50%;
background: #ffffff;
cursor: pointer;
border: none;
box-shadow: 0 0 5px rgba(255, 255, 255, 0.6);
}
.volume-container {
margin-top: 15px;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
#volume {
width: 100px;
}
#volume::-webkit-slider-thumb {
background: #f0f0f0;
}
#play.play {
color: #fff; /* Green (you can switch to orange if preferred) */
background: #20c997;
}
#progress::-webkit-slider-thumb,
#volume::-webkit-slider-thumb {
background: #fff;
}
.screen {
display: none;
padding: 20px;
}
.screen.active {
display: block;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
#playlistScreen ul {
list-style: none;
padding: 0;
}
.playlist-item {
display: flex;
align-items: center;
gap: 15px;
padding: 10px 0;
border-bottom: 1px solid #333;
}
.playlist-item img {
width: 50px;
height: 50px;
object-fit: cover;
border-radius: 8px;
}
.playlist-item .info {
flex: 1;
}
.playlist-item button {
background: #20c997;
color: white;
border: none;
border-radius: 6px;
padding: 6px 10px;
cursor: pointer;
}
.header {
margin-bottom: 20px;
}
.nowPlaying{
font-size: 16px;
}
🎯 JavaScript Functionality
const songs = [
{
title: "Emotional Mess",
artist: "Amy Lynn & the Honey Men",
src: "music1.mp3",
cover: "cover1.jpg"
},
{
title: "Kung Fu Love Tree",
artist: "Quincas Moreira",
src: "music2.mp3",
cover: "cover2.jpg"
},
{
title: "Cottonmouth Strut",
artist: "The Whole Other",
src: "music3.mp3",
cover: "cover3.jpg"
},
{
title: "Emotional Mess",
artist: "Amy Lynn & the Honey Men",
src: "music1.mp3",
cover: "cover1.jpg"
},
{
title: "Kung Fu Love Tree",
artist: "Quincas Moreira",
src: "music2.mp3",
cover: "cover2.jpg"
},
{
title: "Cottonmouth Strut",
artist: "The Whole Other",
src: "music3.mp3",
cover: "cover3.jpg"
}
];
document.addEventListener("DOMContentLoaded", function() {
let songIndex = 0;
const audio = document.getElementById("audio");
const title = document.getElementById("title");
const artist = document.getElementById("artist");
const cover = document.getElementById("cover");
const playBtn = document.getElementById("play");
const prevBtn = document.getElementById("prev");
const nextBtn = document.getElementById("next");
const progress = document.getElementById("progress");
const currentTimeEl = document.getElementById("current-time");
const durationEl = document.getElementById("duration");
const volume = document.getElementById("volume");
window.loadSong = function (song) {
title.textContent = song.title;
artist.textContent = song.artist;
audio.src = song.src;
cover.src = song.cover;
}
window.playSong = function() {
audio.play();
playBtn.innerHTML = '<span class="pause-icon">❚❚</span>';
}
window.pauseSong = function() {
audio.pause();
playBtn.innerHTML = '<span class="play-icon">▶</span>';
}
window.togglePlay = function() {
if (audio.paused) {
window.playSong();
} else {
window.pauseSong();
}
}
function prevSong() {
const wasPlaying = !audio.paused;
songIndex = (songIndex - 1 + songs.length) % songs.length;
loadSong(songs[songIndex]);
if (wasPlaying) playSong(); else pauseSong();
}
// Load initial song
window.loadSong(songs[songIndex]);
document.addEventListener('click', function(e) {
if (
e.target.tagName === 'BUTTON' &&
e.target.classList.contains('btn-playlist') &&
e.target.dataset.index
) {
playFromPlaylist(e.target.dataset.index);
}
})
function nextSong() {
const wasPlaying = !audio.paused;
songIndex = (songIndex + 1) % songs.length;
loadSong(songs[songIndex]);
if (wasPlaying) playSong(); else pauseSong();
}
const volumeSteps = [0.25, 0.5, 0.75, 1, 0]; // 0 is mute
let volumeIndex = 0;
document.getElementById("volumeCycleBtn").addEventListener("click", () => {
volumeIndex = (volumeIndex + 1) % volumeSteps.length;
const newVolume = volumeSteps[volumeIndex];
audio.volume = newVolume;
// Update volume icon
const volumeIcon = document.getElementById("volumeCycleBtn");
if (newVolume === 0) {
volumeIcon.textContent = "🔇";
} else if (newVolume <= 0.25) {
volumeIcon.textContent = "🔈";
} else if (newVolume <= 0.5) {
volumeIcon.textContent = "🔉";
} else {
volumeIcon.textContent = "🔊";
}
});
audio.addEventListener("loadedmetadata", () => {
durationEl.textContent = formatTime(audio.duration);
});
function updateProgress() {
const percent = (audio.currentTime / audio.duration) * 100;
progress.value = percent || 0;
currentTimeEl.textContent = formatTime(audio.currentTime);
// Update background size to reflect progress visually
progress.style.background = `linear-gradient(to right, #20c997 0%, #20c997 ${percent}%, #ccc ${percent}%, #ccc 100%)`;
}
function setProgress(e) {
const percent = e.target.value;
audio.currentTime = (percent / 100) * audio.duration;
}
function formatTime(time) {
const mins = Math.floor(time / 60);
const secs = Math.floor(time % 60).toString().padStart(2, '0');
return `${mins}:${secs}`;
}
// Event listeners
playBtn.addEventListener("click", togglePlay);
prevBtn.addEventListener("click", prevSong);
nextBtn.addEventListener("click", nextSong);
audio.addEventListener("timeupdate", updateProgress);
progress.addEventListener("input", setProgress);
if (volume) {
volume.addEventListener("input", (e) => {
audio.volume = e.target.value;
});
}
audio.addEventListener("ended", nextSong);
});
const playlistEl = document.getElementById("playlist");
for (let index = 0; index < songs.length; index++) {
const song = songs[index];
const li = document.createElement("li");
li.classList.add("playlist-item");
// Create elements manually instead of innerHTML
const img = document.createElement("img");
img.src = song.cover;
img.alt = song.title;
const infoDiv = document.createElement("div");
infoDiv.classList.add("info");
infoDiv.innerHTML = `<strong>${song.title}</strong><br><small>${song.artist}</small>`;
const playButton = document.createElement("button");
playButton.textContent = "▶";
playButton.classList.add('btn-playlist');
playButton.dataset.index = index;
li.appendChild(img);
li.appendChild(infoDiv);
li.appendChild(playButton);
playlistEl.appendChild(li);
}
// ✅ Fixed toggle here: Playlist to Now Playing
function playFromPlaylist(index) {
songIndex = index;
loadSong(songs[songIndex]);
playSong();
// Correct screen switch
document.getElementById("playlistScreen").classList.remove("active");
document.getElementById("nowPlayingScreen").classList.add("active");
}
// Navigate manually from Playlist to Now Playing
document.getElementById("goToPlayer").addEventListener("click", () => {
document.getElementById("playlistScreen").classList.remove("active");
document.getElementById("nowPlayingScreen").classList.add("active");
});
// Back button: Now Playing to Playlist
document.getElementById("backToPlaylist").addEventListener("click", () => {
console.log("Back button clicked");
document.getElementById("nowPlayingScreen").classList.remove("active");
document.getElementById("playlistScreen").classList.add("active");
});
✅ Final Result
- Seamless transition between Now Playing and Playlist
- Clickable songs play instantly
- Fully functioning play/pause/next/prev controls
- Clean Neumorphism UI
- Mobile-friendly with some tweaks