← Back to all tutorials

How to build a custom video player with Tailwind CSS and JavaScript

js-video-player
Published and written on Sep 26 2024 by Michael Andreuzza

Hello and welcome to the tutorial on how to build a custom video player with Tailwind CSS and JavaScript.

In this tutorial, we’ll be building a custom video player that can play and pause a video, and you can customize it to suit your design needs.

What is a Video Player?

A video player is a software tool or interface that allows users to play, pause, rewind, fast-forward, or stop video content. It often includes basic controls like play/pause buttons, volume adjustment, and a progress bar. Custom video players can be designed to provide a unique user experience, integrating seamlessly with the overall style of a website or app.

Use Cases

Custom video players can be utilized in various scenarios:

  1. Online Learning Platforms: Offering a seamless viewing experience for lectures or tutorials.
  2. Media Websites: Custom players can integrate branding and style, making the content visually aligned with the site’s aesthetics.
  3. Product Demos: Allowing users to view product features or tutorials in a visually appealing player.
  4. Streaming Services: Custom controls and interactions enhance user engagement and improve accessibility.
  5. Marketing Videos: For businesses showcasing their products or services, a custom video player can offer a tailored experience.

Let’s build the structure

We’ll start by creating a basic HTML structure for our video player. Keep in mind that classes are removed for brevity, but I’ll keep those classes relevant to the repository.

The video

ID’s

  • id="video": This is the ID of the video element. It is used to reference the video element in JavaScript.
<video id="video" src="/videos/video.mp4"></video>

The controls

The controls have a wrapper with the ID controls. Id’s

  • id="controls": This is the ID of the controls wrapper. It is used to reference the controls in JavaScript.

The play and pause button

Id’s

  • id="playPauseBtn": This is the ID of the play and pause button. It is used to reference the play and pause button in JavaScript, and to set the initial state of the button.

The progress bar

Id’s

  • id="progressBar": This is the ID of the progress bar. It is used to reference the progress bar in JavaScript, and to set the initial value of the progress bar.

The time display

Id’s

  • id="time": This is the ID of the time display, which displays the current time and the total duration of the video.
 <div id="controls">
   <div>
     <button id="playPauseBtn">
       <!---SVG Goes here Here--->
     </button>
     <div>
       <input type="range" id="progressBar" min="0" max="100" value="0" />
     </div>
     <div id="time"> 0:00 / 0:00 </div>
   </div>
 </div>

The full html markdown

<div class="max-w-3xl mx-auto w-full bg-white rounded-2xl mt-12 overflow-hidden">
   <div class="relative aspect-video w-full">
      <video id="video" class="w-full h-full object-contain" src="/videos/video.mp4"></video>
      <div id="controls" class="absolute bottom-0 left-0 right-0 bg-neutral-950 text-white p-4">
         <div class="flex items-center justify-between">
            <button id="playPauseBtn" class="focus:outline-none">
               <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"></path>
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
               </svg>
            </button>
            <div class="flex-grow mx-4">
               <input type="range" id="progressBar" class="w-full" min="0" max="100" value="0" />
            </div>
            <div id="time" class="text-sm"> 0:00 / 0:00 </div>
         </div>
      </div>
   </div>
</div>

Let’s add some JavaScript

We’ll start by adding some JavaScript to the HTML file. This JavaScript will handle the play and pause functionality, as well as update the progress bar and time display. We’ll also add some event listeners to the video and progress bar elements.

The variables

  • const video = document.getElementById("video");: This variable stores a reference to the video element.
  • const playPauseBtn = document.getElementById("playPauseBtn");: This variable stores a reference to the play and pause button.
  • const progressBar = document.getElementById("progressBar");: This variable stores a reference to the progress bar.
const video = document.getElementById("video");
const playPauseBtn = document.getElementById("playPauseBtn");
const progressBar = document.getElementById("progressBar");
const timeDisplay = document.getElementById("time");

The event listeners

  • playPauseBtn.addEventListener("click", togglePlayPause);: This event listener listens for a click on the play and pause button.
  • video.addEventListener("timeupdate", updateProgress);: This event listener listens for a timeupdate event on the video element, which updates the progress bar and time display.
  • progressBar.addEventListener("change", setVideoProgress);: This event listener listens for a change event on the progress bar, which updates the video progress.
playPauseBtn.addEventListener("click", togglePlayPause);
video.addEventListener("timeupdate", updateProgress);
progressBar.addEventListener("change", setVideoProgress);

The togglePlayPause function

This function toggles the play and pause state of the video. It updates the button text and the video’s paused state. It also updates the progress bar and time display. The function is called when the play and pause button is clicked. It checks if the video is paused, and if so, it plays the video.

  • function togglePlayPause(): This is the function definition.
  • if (video.paused): This is a conditional statement that checks if the video is paused.
  • video.play(): This is a function call that plays the video.
  • playPauseBtn.innerHTML: This is a variable that stores the HTML content of the play and pause button.
  • else: This is a conditional statement that executes if the video is not paused.
  • video.pause(): This is a function call that pauses the video.
  • playPauseBtn.innerHTML: This is a variable that stores the HTML content of the play and pause button.
function togglePlayPause() {
   if (video.paused) {
      video.play();
      playPauseBtn.innerHTML = `
                    <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 9v6m4-6v6m7-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
                    </svg>
                `;
   } else {
      video.pause();
      playPauseBtn.innerHTML = `
                    <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"></path>
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
                    </svg>
                `;
   }
}

The updateProgress function

This function updates the progress bar and time display based on the current time and duration of the video.

  • function updateProgress(): This is the function definition. It updates the progress bar and time display.
  • const progress = (video.currentTime / video.duration) * 100;: This is a constant that calculates the progress of the video as a percentage.
  • progressBar.value = progress;: This is a statement that sets the value of the progress bar to the calculated progress.
  • const currentMinutes = Math.floor(video.currentTime / 60);: This is a constant that calculates the current minutes of the video.
  • const currentSeconds = Math.floor(video.currentTime % 60);: This is a constant that calculates the current seconds of the video.
  • const durationMinutes = Math.floor(video.duration / 60);: This is a constant that calculates the duration minutes of the video.
  • const durationSeconds = Math.floor(video.duration % 60);: This is a constant that calculates the duration seconds of the video.
  • timeDisplay.textContent = ${currentMinutes}:${currentSeconds.toString().padStart(2, “0”)} / ${durationMinutes}:${durationSeconds.toString().padStart(2, “0”)};: This is a statement that sets the text content of the time display to the calculated current minutes, current seconds, and duration minutes, duration seconds.
function updateProgress() {
   const progress = (video.currentTime / video.duration) * 100;
   progressBar.value = progress;

   const currentMinutes = Math.floor(video.currentTime / 60);
   const currentSeconds = Math.floor(video.currentTime % 60);
   const durationMinutes = Math.floor(video.duration / 60);
   const durationSeconds = Math.floor(video.duration % 60);

   timeDisplay.textContent = `${currentMinutes}:${currentSeconds.toString().padStart(2, "0")} / ${durationMinutes}:${durationSeconds.toString().padStart(2, "0")}`;
}

The setVideoProgress function

This function updates the video progress based on the value of the progress bar. It also updates the time display.

  • function setVideoProgress(): This is the function definition.
  • const time = (progressBar.value * video.duration) / 100;: This is a constant that calculates the time based on the value of the progress bar and the duration of the video.
  • video.currentTime = time;: This is a statement that sets the current time of the video to the calculated time.
function setVideoProgress() {
   const time = (progressBar.value * video.duration) / 100;
   video.currentTime = time;
}

The full script

const video = document.getElementById("video");
const playPauseBtn = document.getElementById("playPauseBtn");
const progressBar = document.getElementById("progressBar");
const timeDisplay = document.getElementById("time");

playPauseBtn.addEventListener("click", togglePlayPause);
video.addEventListener("timeupdate", updateProgress);
progressBar.addEventListener("change", setVideoProgress);

function togglePlayPause() {
   if (video.paused) {
      video.play();
      playPauseBtn.innerHTML = `
                    <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 9v6m4-6v6m7-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
                    </svg>
                `;
   } else {
      video.pause();
      playPauseBtn.innerHTML = `
                    <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"></path>
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
                    </svg>
                `;
   }
}

function updateProgress() {
   const progress = (video.currentTime / video.duration) * 100;
   progressBar.value = progress;

   const currentMinutes = Math.floor(video.currentTime / 60);
   const currentSeconds = Math.floor(video.currentTime % 60);
   const durationMinutes = Math.floor(video.duration / 60);
   const durationSeconds = Math.floor(video.duration % 60);

   timeDisplay.textContent = `${currentMinutes}:${currentSeconds.toString().padStart(2, "0")} / ${durationMinutes}:${durationSeconds.toString().padStart(2, "0")}`;
}

function setVideoProgress() {
   const time = (progressBar.value * video.duration) / 100;
   video.currentTime = time;
}

Conclusion

Congratulations! You’ve built a custom video player with Tailwind CSS and JavaScript. You can now customize the player to suit your needs and enhance the user experience. Remember to add validation and error handling to ensure the player is always up-to-date and accessible.

Hope you enjoyed this tutorial and have a great day!

/Michael Andreuzza

Did you like this tutorial? Please share it with your friends!

Get lifetime access to every theme available today for $199 $139 and own them forever. Plus, new themes, lifetime updates, use on unlimited projects and enjoy lifetime support.

— No subscription required!