Open In App

Custom Video Player using HTML, CSS and JavaScript

Last Updated : 03 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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:

Screenshot-2023-10-20-170418

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: 100vh;
    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.3s 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.1s 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=
    <link rel="stylesheet" 
          href="style.css">
  
</head>
  
<body>
    <div class="gfg">
        <p>GeeksForGeeks</p>
        <p>Custom Video Player</p>
    </div>
    
    <!-- Video container -->
    <div class="video-container">
        <img src=
               id="video-thumbnail">
        <video id="video">
              
          <!-- Video source -->
            <source
                src=
                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:

gfgvp



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads