Creating a custom music player with album art is a fantastic way to enhance user experience on a website, offering both functionality and visual appeal. With HTML, CSS, and JavaScript, you can build a feature-rich music player that supports playback controls, track navigation, progress tracking, and dynamic album art display. This in-depth guide will walk you through the process of building a modern music player from scratch, including best practices, free AI tools for generating album art, and a complete code example. Whether you're a beginner or an experienced developer, this article will provide you with the tools and knowledge to create an engaging audio experience.
A custom music player offers several advantages over default browser audio controls:
By integrating album art, you create a visually immersive experience that complements the audio content, making it ideal for music websites, portfolios, or personal projects.
The foundation of our music player is the HTML5 <audio>
element, which provides native support for audio playback in modern browsers. It supports formats like MP3, WAV, and OGG, and includes built-in methods for controlling playback via JavaScript.
Here’s a basic <audio>
setup:
<audio id="audioPlayer" src="song.mp3"></audio>
However, to create a custom player, we’ll hide the default controls and build a custom interface with buttons, a progress bar, and album art.
Our music player will include the following features:
To keep things organized, create the following files:
index.html
: The main HTML file.styles.css
: For styling the player.script.js
: For JavaScript logic.assets/
: A folder for audio files and album art images.You’ll also need sample audio files (e.g., song1.mp3
, song2.mp3
) and album art images (e.g., album1.jpg
, album2.jpg
). Ensure all files are royalty-free or licensed for use.
The HTML will include the player interface, album art, and playlist. Here’s a sample:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Music Player with Album Art</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="music-player">
<img id="albumArt" src="assets/default.jpg" alt="Album Art">
<h2 id="trackTitle">Track Title</h2>
<audio id="audioPlayer"></audio>
<div class="progress-container">
<span id="currentTime">0:00</span>
<input type="range" id="progressBar" value="0" max="100">
<span id="duration">0:00</span>
</div>
<div class="controls">
<button id="prevBtn">◀</button>
<button id="playPauseBtn">▶</button>
<button id="nextBtn">▶</button>
</div>
<div class="volume-control">
<input type="range" id="volumeSlider" min="0" max="1" step="0.1" value="1">
</div>
<ul id="playlist"></ul>
</div>
<script src="script.js"></script>
</body>
</html>
<img id="albumArt">
: Displays the album art.<h2 id="trackTitle">
: Shows the current track’s title.<audio id="audioPlayer">
: The audio element (source set via JavaScript).<input type="range" id="progressBar">
: A range input for the progress bar.<input type="range" id="volumeSlider">
: A range input for volume control.<ul id="playlist">
: A list for displaying playlist tracks.The CSS will make the player modern and responsive. Save this in styles.css
:
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #f0f0f0;
margin: 0;
}
.music-player {
background: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 400px;
text-align: center;
}
#albumArt {
width: 100%;
max-width: 300px;
border-radius: 10px;
margin-bottom: 10px;
}
#trackTitle {
font-size: 1.2em;
margin: 10px 0;
}
.progress-container {
display: flex;
align-items: center;
gap: 10px;
margin: 10px 0;
}
#progressBar {
flex: 1;
cursor: pointer;
}
.controls {
display: flex;
justify-content: center;
gap: 20px;
margin: 10px 0;
}
.controls button {
background: #4CAF50;
color: white;
border: none;
padding: 10px;
border-radius: 50%;
cursor: pointer;
font-size: 1.2em;
}
.controls button:hover {
background: #45a049;
}
.volume-control {
margin: 10px 0;
}
#volumeSlider {
width: 100%;
}
#playlist {
list-style: none;
padding: 0;
margin: 10px 0;
}
#playlist li {
padding: 10px;
cursor: pointer;
border-radius: 5px;
}
#playlist li:hover {
background: #f0f0f0;
}
#playlist li.active {
background: #4CAF50;
color: white;
}
@media (max-width: 400px) {
.music-player {
padding: 15px;
}
#albumArt {
max-width: 250px;
}
}
This CSS creates a clean, modern design with a responsive layout, hover effects, and a visually appealing album art display.
The JavaScript will handle playback, track navigation, progress updates, and album art switching. Save this in script.js
:
const audioPlayer = document.getElementById('audioPlayer');
const playPauseBtn = document.getElementById('playPauseBtn');
const prevBtn = document.getElementById('prevBtn');
const nextBtn = document.getElementById('nextBtn');
const progressBar = document.getElementById('progressBar');
const currentTime = document.getElementById('currentTime');
const duration = document.getElementById('duration');
const volumeSlider = document.getElementById('volumeSlider');
const trackTitle = document.getElementById('trackTitle');
const albumArt = document.getElementById('albumArt');
const playlist = document.getElementById('playlist');
const tracks = [
{ title: 'Song 1', src: 'assets/song1.mp3', art: 'assets/album1.jpg' },
{ title: 'Song 2', src: 'assets/song2.mp3', art: 'assets/album2.jpg' },
{ title: 'Song 3', src: 'assets/song3.mp3', art: 'assets/album3.jpg' },
];
let currentTrackIndex = 0;
let isPlaying = false;
function loadTrack(index) {
const track = tracks[index];
audioPlayer.src = track.src;
trackTitle.textContent = track.title;
albumArt.src = track.art;
updatePlaylist();
audioPlayer.load();
}
function updatePlaylist() {
playlist.innerHTML = '';
tracks.forEach((track, index) => {
const li = document.createElement('li');
li.textContent = track.title;
li.classList.toggle('active', index === currentTrackIndex);
li.addEventListener('click', () => {
currentTrackIndex = index;
loadTrack(index);
playTrack();
});
playlist.appendChild(li);
});
}
function playTrack() {
audioPlayer.play();
isPlaying = true;
playPauseBtn.textContent = '❚❚';
}
function pauseTrack() {
audioPlayer.pause();
isPlaying = false;
playPauseBtn.textContent = 'play';
}
function togglePlayPause() {
if (isPlaying) {
pauseTrack();
} else {
playTrack();
}
}
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs < 10 ? '0' : ''}${secs}`;
}
playPauseBtn.addEventListener('click', togglePlayPause);
prevBtn.addEventListener('click', () => {
currentTrackIndex = (currentTrackIndex - 1 + tracks.length) % tracks.length;
loadTrack(currentTrackIndex);
playTrack();
});
nextBtn.addEventListener('click', () => {
currentTrackIndex = (currentTrackIndex + 1) % tracks.length;
loadTrack(currentTrackIndex);
playTrack();
});
audioPlayer.addEventListener('timeupdate', () => {
const { currentTime, duration: durationValue } = audioPlayer;
progressBar.value = (currentTime / durationValue) * 100 || 0;
currentTime.textContent = formatTime(currentTime);
duration.textContent = formatTime(durationValue) || '0:00';
});
progressBar.addEventListener('input', () => {
audioPlayer.currentTime = (progressBar.value / 100) * audioPlayer.duration;
});
volumeSlider.addEventListener('input', () => {
audioPlayer.volume = volumeSlider.value;
});
audioPlayer.addEventListener('ended', () => {
nextBtn.click();
});
loadTrack(currentTrackIndex);
updatePlaylist();
Creating unique album art can be time-consuming, but free AI tools make it easy:
These tools allow you to create professional-looking album art without advanced design experience.
To ensure your music player is accessible:
aria-label="Play or Pause"
).tabindex="0"
.alt
attributes.audioPlayer.duration
is NaN
until metadata loads.Below is the complete code, combining HTML, CSS, and JavaScript.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Music Player with Album Art</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="music-player">
<img id="albumArt" src="assets/default.jpg" alt="Album Art">
<h2 id="trackTitle">Track Title</h2>
<audio id="audioPlayer"></audio>
<div class="progress-container">
<span id="currentTime">0:00</span>
<input type="range" id="progressBar" value="0" max="100">
<span id="duration">0:00</span>
</div>
<div class="controls">
<button id="prevBtn">◀</button>
<button id="playPauseBtn">▶</button>
<button id="nextBtn">▶</button>
</div>
<div class="volume-control">
<input type="range" id="volumeSlider" min="0" max="1" step="0.1" value="1">
</div>
<ul id="playlist"></ul>
</div>
<script src="script.js"></script>
</body>
</html>
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #f0f0f0;
margin: 0;
}
.music-player {
background: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 400px;
text-align: center;
}
#albumArt {
width: 100%;
max-width: 300px;
border-radius: 10px;
margin-bottom: 10px;
}
#trackTitle {
font-size: 1.2em;
margin: 10px 0;
}
.progress-container {
display: flex;
align-items: center;
gap: 10px;
margin: 10px 0;
}
#progressBar {
flex: 1;
cursor: pointer;
}
.controls {
display: flex;
justify-content: center;
gap: 20px;
margin: 10px 0;
}
.controls button {
background: #4CAF50;
color: white;
border: none;
padding: 10px;
border-radius: 50%;
cursor: pointer;
font-size: 1.2em;
}
.controls button:hover {
background: #45a049;
}
.volume-control {
margin: 10px 0;
}
#volumeSlider {
width: 100%;
}
#playlist {
list-style: none;
padding: 0;
margin: 10px 0;
}
#playlist li {
padding: 10px;
cursor: pointer;
border-radius: 5px;
}
#playlist li:hover {
background: #f0f0f0;
}
#playlist li.active {
background: #4CAF50;
color: white;
}
@media (max-width: 400px) {
.music-player {
margin: 15px;
}
#albumArt {
max-width: 250px;
}
}
const audioPlayer = document.getElementById('audioPlayer');
const playPauseBtn = document.getElementById('playPauseBtn');
const prevBtn = document.getElementById('prevBtn');
const nextBtn = document.getElementById('nextBtn');
const progressBar = document.getElementById('progressBar');
const currentTime = document.getElementById('currentTime');
const duration = document.getElementById('duration');
const volumeSlider = document.getElementById('volumeSlider');
const trackTitle = document.getElementById('trackTitle');
const albumArt = document.getElementById('albumArt');
const playlist = document.getElementById('playlist');
const tracks = [
{ title: 'Song 1', src: 'assets/song1.mp3', art: 'assets/album1.jpg' },
{ title: 'Song 2', src: 'assets/song2.mp3', art: 'assets/album2.jpg' },
{ title: 'Song 3', src: 'assets/song3.mp3', art: 'assets/album3.jpg' },
];
let currentTrackIndex = 0;
let isPlaying = false;
function loadTrack(index) {
const track = tracks[index];
audioPlayer.src = track.src;
trackTitle.textContent = track.title;
albumArt.src = track.art;
updatePlaylist();
audioPlayer.load();
}
function updatePlaylist() {
playlist.innerHTML = '';
tracks.forEach((track, index) => {
tracks.forEach((track, index) => {
const li = document.createElement('li');
li.textContent = track.title;
li.classList.toggle('active', index === currentTrackIndex);
li.addEventListener('click', () => {
currentTrackIndex = index;
loadTrack(index);
playTrack();
});
playlist.appendChild(li);
});
});
}
function playTrack() {
audioPlayer.play();
isPlaying = true;
playPauseBtn.textContent = '❚❚';
}
function pauseTrack() {
audioPlayer.pause();
isPlaying = false;
playPauseBtn.textContent = '▶';
}
function togglePlayPause() {
if (isPlaying) {
pauseTrack();
} else {
playTrack();
}
}
function formatTime(seconds) {
const minutes = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${minutes}:${secs < 10 ? '0' : ''}${secs}`;
}
playPauseBtn.addEventListener('click', togglePlayPause);
prevBtn.addEventListener('click', () => {
currentTrackIndex = (currentTrackIndex - 1 + tracks.length) % tracks.length;
loadTrack(currentTrackIndex);
playTrack();
});
nextBtn.addEventListener('click', () => {
currentTrackIndex = (currentTrackIndex + tracks.length + 1) % tracks.length;
loadTrack(currentTrackIndex);
playTrack();
});
audioPlayer.addEventListener('timeupdate', () => {
const { currentTime, durationValue } = audioPlayer;
progressBar.value = (currentTime / durationValue) * duration100 || currentTime.textContent = formatTime(currentTime);
duration.textContent = formatTime(durationValue) || duration'0:00';
});
progressBar.addEventListener('input', () => {
audioPlayer.currentTime = (progressBar.value / duration100) * audioPlayer.duration;
});
volumeSlider.addEventListener('input', () => {
audioPlayer.volume = volumeSlider.value;
});
audioPlayer.addEventListener('ended', () => {
nextBtn.click();
});
loadTrack(currentTrackIndex);
updatePlaylistTrack(currentTrackIndex);
Building a music player with album art is a powerful way to combine functionality with visual appeal. By leveraging HTML5 audio, CSS for styling, and JavaScript for interactivity, you can create a modern, responsive player that enhances user engagement. Free AI tools like Canva, Artbreeder, and Runway simplify album art creation, while best practices ensure accessibility and compatibility. Use the complete code provided to kickstart your project and customize it to fit your needs. Start building your music player today to deliver an immersive audio experience for your audience!