Custom Video Player using HTML, CSS and JavaScript
In this article, we are going to implement a Custom Video Player using HTML CSS JavaScript. We will be using HTML to structure our project, CSS for designing purpose and JavaScript will be used to provide the required functionality.
Preview of final Output: Let us have a look at how the final output will look like:
Prerequisites of Video Player
Approach to create Video Player
- Create the basic structure of the project using HTML, like create different <div> tags, and add control buttons for play/pause, skip forward/backward, mute, and a volume slider, also create a video element with source for your video.
- Style the structure with CSS using classes and elements.
- In JavaScript,
- Add functionality to each of the buttons such as play | pause, mute | unmute, volume controls
- Add Show | hide the control bar on mouse enter | leave functionality.
Example: Write the following code in respective files:
- script.js: This file implements the functionalities of Custom Video Player
- style.css: This file contains the styling of Custom Video Player
- index.html: This file contains the basic structure on Video Player
Javascript
// Script.js // Select the elements const video = document.getElementById( "video" ); const videoThumbnail = document.getElementById( "video-thumbnail" ); const playpause = document.getElementById( "play-pause" ); const frwd = document.getElementById( "skip-10" ); const bkwrd = document.getElementById( "skipminus-10" ); const volume = document.getElementById( "volume" ); const mutebtn = document.getElementById( "mute" ); const videoContainer = document.querySelector( ".video-container" ); const controls = document.querySelector( ".controls" ); const progressBar = document.querySelector( ".progress-bar" ); const playbackline = document.querySelector( ".playback-line" ); const currentTimeRef = document.getElementById( "current-time" ); const maxDuration = document.getElementById( "max-duration" ); const timeFormatter = (timeInput) => { let minute = Math.floor(timeInput / 60); minute = minute < 10 ? "0" + minute : minute; let second = Math.floor(timeInput % 60); second = second < 10 ? "0" + second : second; return `${minute}:${second}`; }; // Play-Pause playpause.addEventListener( "click" , function () { if (video.paused) { videoThumbnail.style.display = "none" ; video.play(); playpause.innerHTML = '<i class="fa-solid fa-pause"></i>' ; } else { video.pause(); playpause.innerHTML = '<i class="fa-solid fa-play"></i>' ; } }); let isPlaying = false ; // Function to toggle play/pause function togglePlayPause() { if (isPlaying) { video.pause(); playpause.innerHTML = '<i class="fa-solid fa-play"></i>' ; } else { videoThumbnail.style.display = "none" ; video.play(); playpause.innerHTML = '<i class="fa-solid fa-pause"></i>' ; } isPlaying = !isPlaying; } document.addEventListener( "keydown" , function (event) { if (event.key === 32 || event.key === " " ) { event.preventDefault(); // Prevent scrolling the page down togglePlayPause(); } }); // Event listener for the video to // update the isPlaying flag video.addEventListener( "play" , function () { isPlaying = true ; }); video.addEventListener( "pause" , function () { isPlaying = false ; }); video.addEventListener( "ended" , function () { playpause.innerHTML = '<i class="fa-solid fa-play"></i>' ; }); // Forward 5 sec or backward 5 sec frwd.addEventListener( "click" , function () { video.currentTime += 5; }); bkwrd.addEventListener( "click" , function () { video.currentTime -= 5; }); // Mute or Unmute mutebtn.addEventListener( "click" , function () { if (video.muted) { video.muted = false ; mutebtn.innerHTML = '<i class="fas fa-volume-up"></i>' ; volume.value = video.volume; } else { video.muted = true ; mutebtn.innerHTML = '<i class="fa-solid fa-volume-xmark"></i>' ; volume.value = 0; } }); document.addEventListener( "keydown" , function (event) { if (event.key === "M" || event.key === "m" ) { event.preventDefault(); if (video.muted) { video.muted = false ; mutebtn.innerHTML = '<i class="fas fa-volume-up"></i>' ; volume.value = video.volume; } else { video.muted = true ; mutebtn.innerHTML = '<i class="fa-solid fa-volume-xmark"></i>' ; volume.value = 0; } } }); volume.addEventListener( "input" , function () { video.volume = volume.value; if (video.volume === 0) { mutebtn.innerHTML = '<i class="fa-solid fa-volume-xmark"></i>' ; } else { mutebtn.innerHTML = '<i class="fas fa-volume-up"></i>' ; } }); // Hide or unhide controllers div videoContainer.addEventListener( "mouseenter" , () => { controls.style.opacity = 1; }); videoContainer.addEventListener( "mouseleave" , () => { controls.style.opacity = 0; }); // Update the playback line as the video plays video.addEventListener( "timeupdate" , () => { const currentTime = video.currentTime; const duration = video.duration; const percentage = (currentTime / duration) * 100; progressBar.style.width = percentage + "%" ; }); function showThumbnail() { videoThumbnail.style.display = "block" ; } // Reseting the playback line when the video ends video.addEventListener( "ended" , () => { progressBar.style.width = "0%" ; showThumbnail(); }); setInterval(() => { currentTimeRef.innerHTML = timeFormatter(video.currentTime); maxDuration.innerText = timeFormatter(video.duration); }, 1); playbackline.addEventListener( "click" , (e) => { let timelineWidth = playbackline.clientWidth; video.currentTime = (e.offsetX / timelineWidth) * video.duration; }); |
CSS
/* Style.css */ * { margin : 0 ; padding : 0 ; } body { display : flex; align-items: center ; justify- content : center ; height : 100 vh; flex- direction : column; border : none ; } .gfg { padding-bottom : 10px ; display : flex; justify- content : space-around; flex- direction : column; font-size : 24px ; font-weight : 600 ; color : #01940b ; align-items: center ; } .video-container { max-width : 500px ; max-height : 300px ; position : relative ; border : 1px ; border-style : ridge ; margin : 0 auto ; background-color : black ; } #video-thumbnail { position : absolute ; width : 100% ; height : 100% ; object-fit: cover; cursor : pointer ; } #video, img { width : 100% ; height : 100% ; } .controls { position : absolute ; bottom : 0px ; left : 0 ; right : 0 ; height : 40px ; background-color : rgba( 0 , 0 , 0 , 0.7 ); display : flex; justify- content : space-between; align-items: center ; padding : 10px ; opacity: 0 ; transition: opacity 0.3 s ease-in-out; } .controls button { background-color : transparent ; border : none ; color : #fff ; font-size : 20px ; cursor : pointer ; outline : none ; } . left { position : relative ; top : 1% ; width : 70px ; display : flex; justify- content : space-between; } .video-timer { position : relative ; top : 5.2px ; right : 6px ; display : flex; flex- direction : row; color : #efefef ; margin-left : 15px ; font-size : 12px ; } #separator { margin : 0 5px ; font-size : 16px ; font-family : "Open sans" ; } . right { position : relative ; padding : 10px ; top : 1.5px ; } .fa-volume-up, .fa- solid { font-size : small ; padding : 5px ; color : rgb ( 255 , 255 , 255 ); } button, input { background-color : transparent ; border : none ; cursor : pointer ; font-size : 20px ; } .volume-container { display : flex; align-items: center ; } #volume { position : relative ; left : 5px ; width : 50px ; height : 3px ; } #mute { cursor : pointer ; } .playback-line { position : relative ; top : 2.7px ; height : 4px ; background-color : #ddd ; width : 40% ; cursor : pointer ; } .progress-bar { height : 100% ; width : 0 ; background-color : #0078d4 ; transition: width 0.1 s linear; } |
HTML
<!DOCTYPE html> < html lang = "en" > < head > < meta charset = "UTF-8" > < meta name = "viewport" content=" width = device -width, initial-scale = 1 .0"> < title >Video Player-GFG</ title > < link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" > < link rel = "stylesheet" href = "style.css" > </ head > < body > < div class = "gfg" > < p >w3wiki</ p > < p >Custom Video Player</ p > </ div > <!-- Video container --> < div class = "video-container" > < img src = "https://media.w3wiki.net/wp-content/uploads/20231020170918/Thumbnail-(1).jpg" id = "video-thumbnail" > < video id = "video" > <!-- Video source --> < source src = "https://media.w3wiki.net/wp-content/uploads/20231020155223/Full-Stack-Development-_-LIVE-Classes-_-w3wiki.mp4" type = "video/mp4" > </ video > <!-- Controlers continer --> < div class = "controls" > <!-- Left controller div --> < div class = "left" > < button id = "skipminus-10" > < i class = "fa-solid fa-backward" ></ i > </ button > < button id = "play-pause" > < i class = "fa-solid fa-play" ></ i > </ button > < button id = "skip-10" > < i class = "fa-solid fa-forward" ></ i > </ button > </ div > <!-- div for progress bar --> < div class = "video-timer" > < span id = "current-time" >00:00</ span > < span id = "separator" >/</ span > < span id = "max-duration" >00:00</ span > </ div > < div class = "playback-line" > < div class = "progress-bar" ></ div > </ div > <!-- Right controller div --> < div class = "right" > < div class = "volume-container" > < div id = "mute" > < i class = "fas fa-volume-up" ></ i > </ div > < input type = "range" id = "volume" min = "0" max = "1" step = "0.01" value = "1" > </ div > </ div > </ div > </ div > < script src = "script.js" ></ script > </ body > </ html > |
Output: