Build a Real-Time PHP Chat App with MySQL & JavaScript
Learn how to create a real-time PHP chat app using MySQL and JavaScript with user login, typing status, chat history deletion, and a modern, responsive UI.
Suggested:
Create a fully functional music player app using HTML, CSS, and JavaScript. Learn to implement play/pause controls, next/previous track navigation, etc,.
Building a custom music player app is a fantastic way to practice front-end web development and create something both functional and fun. In this tutorial, we'll walk you through building a Music Player App with essential features:
Let’s dive in!
Table of contents [Show]
We'll start with the basic markup that houses the player controls, progress bar, volume slider, and track list.
<!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="styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body>
<div class="music-player">
<div class="player-header">
<h1>Music Player</h1>
<div class="player-controls-top">
<button id="shuffle-btn" class="control-btn" title="Shuffle">
<i class="fas fa-random"></i>
</button>
<button id="repeat-btn" class="control-btn" title="Repeat">
<i class="fas fa-redo"></i>
</button>
</div>
</div>
<div class="album-art">
<img id="album-art" src="https://via.placeholder.com/300" alt="Album Art">
</div>
<div class="song-info">
<h2 id="song-title">Song Title</h2>
<p id="artist-name">Artist Name</p>
</div>
<div class="progress-container">
<span id="current-time">0:00</span>
<input type="range" id="progress-bar" value="0">
<span id="duration">0:00</span>
</div>
<div class="player-controls">
<button id="prev-btn" class="control-btn" title="Previous">
<i class="fas fa-step-backward"></i>
</button>
<button id="play-btn" class="control-btn play-pause" title="Play">
<i class="fas fa-play"></i>
</button>
<button id="next-btn" class="control-btn" title="Next">
<i class="fas fa-step-forward"></i>
</button>
</div>
<div class="volume-control">
<i class="fas fa-volume-down"></i>
<input type="range" id="volume-slider" min="0" max="1" step="0.01" value="0.7">
<i class="fas fa-volume-up"></i>
</div>
<div class="queue-container">
<h3>Up Next</h3>
<ul id="song-queue">
<!-- Songs will be added here dynamically -->
</ul>
</div>
</div>
<audio id="audio-player"></audio>
<script src="script.js"></script>
</body>
</html>Let's make the player visually appealing and responsive.
:root {
--primary-color: #4a76a8;
--secondary-color: #f5f5f5;
--text-color: #333;
--highlight-color: #6ba1d8;
--shadow-color: rgba(0, 0, 0, 0.2);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: var(--secondary-color);
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.music-player {
background-color: white;
border-radius: 15px;
box-shadow: 0 10px 30px var(--shadow-color);
width: 100%;
max-width: 400px;
padding: 25px;
text-align: center;
}
.player-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.player-header h1 {
font-size: 1.5rem;
color: var(--primary-color);
}
.control-btn {
background: none;
border: none;
color: var(--primary-color);
font-size: 1.2rem;
cursor: pointer;
padding: 8px;
border-radius: 50%;
transition: all 0.3s ease;
}
.control-btn:hover {
background-color: var(--secondary-color);
transform: scale(1.1);
}
.album-art {
margin: 0 auto 20px;
width: 200px;
height: 200px;
border-radius: 50%;
overflow: hidden;
box-shadow: 0 5px 15px var(--shadow-color);
animation: rotateAlbumArt 20s linear infinite;
animation-play-state: paused;
}
.album-art img {
width: 100%;
height: 100%;
object-fit: cover;
}
.music-player.playing .album-art {
animation-play-state: running;
}
.song-info {
margin-bottom: 20px;
}
.song-info h2 {
font-size: 1.5rem;
margin-bottom: 5px;
}
.song-info p {
color: #666;
font-size: 1rem;
}
.progress-container {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.progress-container span {
font-size: 0.8rem;
color: #666;
width: 40px;
}
#progress-bar {
flex-grow: 1;
margin: 0 10px;
height: 6px;
-webkit-appearance: none;
appearance: none;
background-color: #ddd;
border-radius: 3px;
cursor: pointer;
}
#progress-bar::-webkit-slider-thumb {
-webkit-appearance: none;
width: 15px;
height: 15px;
background-color: var(--primary-color);
border-radius: 50%;
cursor: pointer;
}
.player-controls {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
}
.play-pause {
background-color: var(--primary-color);
color: white;
width: 50px;
height: 50px;
border-radius: 50%;
margin: 0 20px;
font-size: 1.5rem;
display: flex;
justify-content: center;
align-items: center;
}
.play-pause:hover {
background-color: var(--highlight-color);
transform: scale(1.1);
}
.volume-control {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
}
.volume-control i {
color: var(--primary-color);
margin: 0 10px;
}
#volume-slider {
width: 100px;
height: 5px;
-webkit-appearance: none;
appearance: none;
background-color: #ddd;
border-radius: 3px;
cursor: pointer;
}
#volume-slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
background-color: var(--primary-color);
border-radius: 50%;
cursor: pointer;
}
.queue-container {
text-align: left;
margin-top: 20px;
max-height: 200px;
overflow-y: auto;
}
.queue-container h3 {
color: var(--primary-color);
margin-bottom: 10px;
font-size: 1rem;
}
#song-queue {
list-style-type: none;
}
#song-queue li {
padding: 8px 10px;
border-bottom: 1px solid #eee;
cursor: pointer;
transition: background-color 0.2s;
}
#song-queue li:hover {
background-color: var(--secondary-color);
}
#song-queue li.playing {
color: var(--primary-color);
font-weight: bold;
}
.active {
color: var(--highlight-color);
}
@keyframes rotateAlbumArt {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Responsive Design */
@media (max-width: 480px) {
.music-player {
padding: 15px;
}
.album-art {
width: 150px;
height: 150px;
}
.song-info h2 {
font-size: 1.2rem;
}
.play-pause {
width: 45px;
height: 45px;
margin: 0 15px;
}
}Now the fun part — powering up the player with JavaScript.
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const audioPlayer = document.getElementById('audio-player');
const playBtn = document.getElementById('play-btn');
const prevBtn = document.getElementById('prev-btn');
const nextBtn = document.getElementById('next-btn');
const progressBar = document.getElementById('progress-bar');
const currentTimeEl = document.getElementById('current-time');
const durationEl = document.getElementById('duration');
const volumeSlider = document.getElementById('volume-slider');
const shuffleBtn = document.getElementById('shuffle-btn');
const repeatBtn = document.getElementById('repeat-btn');
const songTitle = document.getElementById('song-title');
const artistName = document.getElementById('artist-name');
const albumArt = document.getElementById('album-art');
const songQueue = document.getElementById('song-queue');
const musicPlayer = document.querySelector('.music-player');
// Music library
const songs = [
{
title: "Blinding Lights",
artist: "The Weeknd",
src: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
cover: "https://i.scdn.co/image/ab67616d0000b2734718e2b124f79258be7bc452"
},
{
title: "Save Your Tears",
artist: "The Weeknd",
src: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3",
cover: "https://i.scdn.co/image/ab67616d0000b2738863bc11d2aa12b54f5aeb36"
},
{
title: "Starboy",
artist: "The Weeknd ft. Daft Punk",
src: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-3.mp3",
cover: "https://i.scdn.co/image/ab67616d0000b2734718e2b124f79258be7bc452"
},
{
title: "Take My Breath",
artist: "The Weeknd",
src: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-4.mp3",
cover: "https://i.scdn.co/image/ab67616d0000b2734718e2b124f79258be7bc452"
},
{
title: "Die For You",
artist: "The Weeknd",
src: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-5.mp3",
cover: "https://i.scdn.co/image/ab67616d0000b2734718e2b124f79258be7bc452"
}
];
// Player state
let currentSongIndex = 0;
let isPlaying = false;
let isShuffled = false;
let isRepeated = false;
let originalQueue = [...songs];
let shuffledQueue = [];
// Initialize player
function initPlayer() {
loadSong(currentSongIndex);
updateQueue();
}
// Load song
function loadSong(index) {
const song = songs[index];
songTitle.textContent = song.title;
artistName.textContent = song.artist;
albumArt.src = song.cover;
audioPlayer.src = song.src;
// Update active song in queue
const queueItems = songQueue.querySelectorAll('li');
queueItems.forEach(item => item.classList.remove('playing'));
queueItems[index].classList.add('playing');
}
// Play song
function playSong() {
isPlaying = true;
musicPlayer.classList.add('playing');
playBtn.innerHTML = '<i class="fas fa-pause"></i>';
audioPlayer.play();
}
// Pause song
function pauseSong() {
isPlaying = false;
musicPlayer.classList.remove('playing');
playBtn.innerHTML = '<i class="fas fa-play"></i>';
audioPlayer.pause();
}
// Next song
function nextSong() {
if (isRepeated) {
audioPlayer.currentTime = 0;
playSong();
return;
}
currentSongIndex++;
if (currentSongIndex >= songs.length) {
currentSongIndex = 0;
}
loadSong(currentSongIndex);
if (isPlaying) {
playSong();
}
}
// Previous song
function prevSong() {
if (audioPlayer.currentTime > 3) {
audioPlayer.currentTime = 0;
return;
}
currentSongIndex--;
if (currentSongIndex < 0) {
currentSongIndex = songs.length - 1;
}
loadSong(currentSongIndex);
if (isPlaying) {
playSong();
}
}
// Update progress bar
function updateProgressBar() {
const { currentTime, duration } = audioPlayer;
const progressPercent = (currentTime / duration) * 100;
progressBar.value = progressPercent;
// Update time displays
currentTimeEl.textContent = formatTime(currentTime);
if (duration) {
durationEl.textContent = formatTime(duration);
}
}
// Set progress bar
function setProgressBar(e) {
const width = this.clientWidth;
const clickX = e.offsetX;
const duration = audioPlayer.duration;
audioPlayer.currentTime = (clickX / width) * duration;
}
// Format time
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs < 10 ? '0' : ''}${secs}`;
}
// Set volume
function setVolume() {
audioPlayer.volume = this.value;
}
// Toggle shuffle
function toggleShuffle() {
isShuffled = !isShuffled;
shuffleBtn.classList.toggle('active');
if (isShuffled) {
// Create a shuffled queue
shuffledQueue = [...songs];
for (let i = shuffledQueue.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffledQueue[i], shuffledQueue[j]] = [shuffledQueue[j], shuffledQueue[i]];
}
songs.splice(0, songs.length, ...shuffledQueue);
} else {
// Restore original queue
songs.splice(0, songs.length, ...originalQueue);
}
// Update current song index
const currentSong = originalQueue[currentSongIndex];
currentSongIndex = songs.findIndex(song => song.title === currentSong.title);
updateQueue();
}
// Toggle repeat
function toggleRepeat() {
isRepeated = !isRepeated;
repeatBtn.classList.toggle('active');
}
// Update song queue
function updateQueue() {
songQueue.innerHTML = '';
songs.forEach((song, index) => {
const li = document.createElement('li');
li.textContent = `${song.title} - ${song.artist}`;
li.addEventListener('click', () => {
currentSongIndex = index;
loadSong(currentSongIndex);
if (isPlaying) {
playSong();
}
});
if (index === currentSongIndex) {
li.classList.add('playing');
}
songQueue.appendChild(li);
});
}
// Event listeners
playBtn.addEventListener('click', () => {
isPlaying ? pauseSong() : playSong();
});
prevBtn.addEventListener('click', prevSong);
nextBtn.addEventListener('click', nextSong);
audioPlayer.addEventListener('timeupdate', updateProgressBar);
audioPlayer.addEventListener('ended', nextSong);
audioPlayer.addEventListener('loadedmetadata', updateProgressBar);
progressBar.addEventListener('click', setProgressBar);
volumeSlider.addEventListener('input', setVolume);
shuffleBtn.addEventListener('click', toggleShuffle);
repeatBtn.addEventListener('click', toggleRepeat);
// Initialize player
initPlayer();
});
Feel free to copy the code snippets above, tweak the styles, add your own tracks, and create your unique music experience.
Happy coding and happy listening! 🎵
Learn how to create a real-time PHP chat app using MySQL and JavaScript with user login, typing status, chat history deletion, and a modern, responsive UI.
Instantly extract editable text from images with our free online OCR demo powered by Tesseract.js. Upload photos and convert them to text in seconds.
A modern PHP-based domain search tool with AJAX, DNS checks, and WHOIS fallback. Get instant domain availability results and smart suggestions in a fast, elegant UI.