DEV Community

Lakshyaraj Dash
Lakshyaraj Dash

Posted on • Edited on

Custom HTML video player

Hello developers! In this tutorial I will teach you all how you can create your custom HTML video player using css and JavaScript.

First Let's create the basic html structure:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Custom Video Player - HTML, CSS and JavaScript</title>
    <link href="./style.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <div class="video-container">
            <video src="./video.mp4" width="100%" height="auto" id="video"></video><br>
        </div>
        <div class="progress-container">
            <span id="currentTime"></span>&nbsp;<input type="range" name="seekbar" id="seekbar" min="0" max="100" style="width: 100%;">&nbsp;<span id="videoDuration"></span>
        </div>
        <br>
        <div style="margin: auto; display: block;">
            <div class="controllers">
                <div class="play-controllers">
                    <button class="btn" id="rewindBtn"><span class="material-icons">fast_rewind</span></button>
                    <button class="btn" id="playBtn"><span class="material-icons">play_circle</span></button>
                    <button class="btn" id="forwardBtn"><span class="material-icons">fast_forward</span></button>
                </div>
                <div class="volume-controllers">
                    <button class="btn" id="muteBtn"><span class="material-icons">volume_off</span></button>
                    <span class="material-icons" id="volume_icon">volume_up</span>
                    <input type="range" name="volume" id="volume" min="0" max="100" style="width: 100%;">
                    <span id="volumePercent"></span>
                </div>
            </div>
        </div>
    </div>

    <script src="./script.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Next we will write the css for designing our pages

@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap');

* {
  margin: 0;
  padding: 0;
  font-family: 'Inter', sans-serif;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background: skyblue;
}

.container {
  width: 50%;
  background: white;
  padding: 8px;
  border-radius: 4px;
}

.video-container {
  padding: 6px;
  background: #000;
  border-radius: 4px;
}

.progress-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.volume-controllers {
  display: flex;
  align-items: center;
}

.btn {
  width: fit-content;
  height: fit-content;
  padding: 2px;
  cursor: pointer;
  background: #d3d3d3;
  border: none;
  border-radius: 4px;
}

.material-icons {
  display: inline-block;
  font-size: 24px;
  line-height: 1;
  vertical-align: middle;
  padding-bottom: 0;
}

.controllers {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
Enter fullscreen mode Exit fullscreen mode

At last let us wrap up by completing the javascript logic

// Initialize the global variables
let video = document.getElementById("video"); 
let playBtn = document.getElementById("playBtn");
let videoDuration = document.getElementById("videoDuration");
let currentTime = document.getElementById("currentTime");
let volume = document.getElementById("volume");
let volume_icon = document.getElementById("volume_icon");
let volumePercent = document.getElementById("volumePercent");
let muteBtn = document.getElementById("muteBtn");
let seekbar = document.getElementById("seekbar");
let rewindBtn = document.getElementById("rewindBtn");
let forwardBtn = document.getElementById("forwardBtn");

// Set the seekbar value to current time of the video
seekbar.value = video.currentTime;
currentTime.innerHTML = '0:0:0' // Set the initial value of current time to 0:0:0

video.addEventListener("loadedmetadata", () => {
    const duration = Math.floor(video.duration); // Get the video duration
    // Get hours, minutes and seconds from the duration
    const hours = Math.floor(duration / 3600);
    const minutes = Math.floor((duration - (hours * 3600)) / 60);
    const seconds = duration - (hours * 3600) - (minutes * 60);
    videoDuration.innerHTML = `${hours}:${minutes}:${seconds}`;

    // Set the initial video volume to 0.5 (50%)
    video.volume = 0.5;
    volume.value = video.volume * 100;
    volumePercent.innerHTML = `${volume.value}%`
})

// Play the video
playBtn.addEventListener("click", () => {
    if (video.paused) {
        video.play();
        // Update the current timestamp of the video
        video.addEventListener("timeupdate", () => {
            const duration = Math.floor(video.currentTime);
            const hours = Math.floor(duration / 3600);
            const minutes = Math.floor((duration - (hours * 3600)) / 60);
            const seconds = duration - (hours * 3600) - (minutes * 60);
            currentTime.innerHTML = `${hours}:${minutes}:${seconds}`;
            // Update the seekbar value
            seekbar.value = (video.currentTime / video.duration) * 100;
        })
        playBtn.innerHTML = `<span class="material-icons">pause_circle</span>`;
    } else {
        video.pause();
        playBtn.innerHTML = `<span class="material-icons">play_circle</span>`;
    }
})

// Reset all the values when video has ended
video.addEventListener("ended", () => {
    seekbar.value = 0;
    video.currentTime = 0;
    playBtn.innerHTML = `<span class="material-icons">play_circle</span>`;
})

let interval;
// Rewind the video for 10 seconds
rewindBtn.addEventListener("mousedown", () => {
    interval = setInterval(() => {
        video.currentTime -= 10;
    }, 100)
})
rewindBtn.addEventListener("mouseup", () => {
   clearInterval(interval)
})

// Forward the video for 10 seconds
forwardBtn.addEventListener("mousedown", () => {
    interval = setInterval(() => {
        video.currentTime += 10;
    }, 100)
})
forwardBtn.addEventListener("mouseup", () => {
   clearInterval(interval)
})

// Switch to the particular timestamp of the video on seekbar changes
seekbar.addEventListener("input", () => {
    let duration = video.duration;
    let progress = seekbar.value;
    let currentTime = (progress / 100) * duration;
    video.currentTime = currentTime;
    const totalSeconds = Math.floor(video.currentTime);
    const hours = Math.floor(totalSeconds / 3600);
    const minutes = Math.floor((totalSeconds - (hours * 3600)) / 60);
    const seconds = totalSeconds - (hours * 3600) - (minutes * 60);
    currentTime.innerHTML = `${hours}:${minutes}:${seconds}`;
})

// Volume change functionality
volume.addEventListener("input", (e) => {
    video.volume = e.target.value / 100;
    volumePercent.innerHTML = `${e.target.value}%`
    if (e.target.value == 0) {
        volume_icon.innerHTML = 'volume_off'
    } else {
        volume_icon.innerHTML = 'volume_up'
    }
})

// Mute or Unmute the video
muteBtn.addEventListener("click", () => {
    if (video.muted) {
        volume.value = video.volume * 100;
        video.muted = false; // Unmute the video
        volume_icon.innerHTML = 'volume_up'
        muteBtn.innerHTML = `<span class="material-icons">volume_off</span>`;
    } else {
        volume.value = 0;
        video.muted = true; // Mute the video
        volume_icon.innerHTML = 'volume_off'
        muteBtn.innerHTML = `<span class="material-icons">volume_up</span>`;
    }
    volumePercent.innerHTML = `${volume.value}%`
})
Enter fullscreen mode Exit fullscreen mode

Test the above code and like this post if you like my project.

Image of PulumiUP 2025

Explore What’s Next in DevOps, IaC, and Security

Join us for demos, and learn trends, best practices, and lessons learned in Platform Engineering & DevOps, Cloud and IaC, and Security.

Save Your Spot

Top comments (0)