DEV Community

Cover image for Interactive video transition with Next.js
The Opinionated Dev
The Opinionated Dev

Posted on • Edited on

Interactive video transition with Next.js

Not so long ago I worked at an advertising company where my team was responsible for creating custom campaigns in the form of websites for our clients.
I’ve worked with several big companies at this time, and one of their favourite was the component we are about to create. Essentially, it’s just a video that gets played when you land on the page, and when it finishes it slowly disappears allowing you to access the website, click buttons etc. Obviously the better video you have to show the user, the bigger the “wow” factor will be.

You can find the Github repository here with the completed code.


Now, we’ll start with creating a new component called VideoReveal and have this code for it:

import { useRef } from "react";

interface VideoRevelProps {
  onVideoEnd: () => void;
}

export const VideoReveal = ({ onVideoEnd }: VideoRevelProps) => {
  const wrapperRef = useRef<HTMLDivElement | null>(null);

  const handleVideoEnded = () => {
    wrapperRef?.current?.classList?.add("opacity-0", "pointer-events-none");

    setTimeout(() => {
      onVideoEnd();
    }, 500);
  };

  return (
    <div
      ref={wrapperRef}
      onClick={handleVideoEnded}
      className="fixed top-0 left-0 w-full h-full z-50 transition-opacity duration-500"
    >
      <video
        autoPlay
        muted
        className="w-full h-full object-cover"
        onEnded={handleVideoEnded}
      >
        <source src="/door.mp4" type="video/mp4" />
      </video>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Here’s what happens

We have a video defined here that has the autoplay property, meaning it will start playing the video as soon the component mounts. We also set it to take the full height and screen of the viewport, and gave it a z-index to make it appear over everything already on the page.

Once this video ends, we want to remove this component. But instead of abruptly unmounting the component, we set it’s opacity to 0 over 500ms and also invoke our onVideoEnd once the CSS transition finished (500ms).

What do we need the onVideoEnd callback?

In the parent component where you want to use the VideoReveal component, here’s how you can use it:

"use client";

import { VideoReveal } from "./components/VideoReveal";
import { useState } from "react";

export default function Home() {
  const [isVideoPlaying, setIsVideoPlaying] = useState(true);

  return (
    <main>
      <h1>Homepage content</h1>
      {isVideoPlaying ? (
        <VideoReveal onVideoEnd={() => setIsVideoPlaying(false)} />
      ) : null}
    </main>
  );
}
Enter fullscreen mode Exit fullscreen mode

With this we mount our VideoReveal because isVideoPlaying is set to true by default and the video start playing. Once the video is finished playing, it calls whatever we pass in to onVideoEnd.

In this scenario, we know that when the video stopped playing, we want to remove our video component as we don’t need it anymore, and we want to display the content on the page so the user can interact with it etc.

Disclaimer

This solution might not be for you if you want the fastest page and interactivity for the user. This is meant to be used as more of a creative approach to “woo” or “charm” the user.

That’s all, hope you enjoyed it and let me know if you have any questions, I’m happy to answer.

You can find the Github repository here with the completed code.

Top comments (0)