Creating Netflix Style Overlay Transitions

Banner for a MediaJam post

Emma Alder

Transitions are vital ingredients that make a website stand out. They make for a great user experience and have been explored a great deal these last few years.

This tutorial will walk you through handling video transitions in our web applications by building a Netflix-style video player using React Player and Framer motion frameworks.

What we'll be building

Similar to Netflix on smart TVs, when our video player mounts, our video starts playing automatically after three seconds. The video has an overlay of the video information adnd a button to play the video. On clicking play, the video overlay fades out, and the video continues playing. When the video ends, the overlay reappears.

Check out the Codesandbox to get started quickly.

1<CodeSandbox id="Hackmamba-Video-Player" title="Creating Netflix Style Overlay Transitions"/>

GitHub URL:


To get the most out of this tutorial, we need the following:

  • A basic understanding of CSS and React Hooks.
  • Node and it’s package manager, npm. Run the command node -v && npm -v to verify we have them, installed, or install them from here..
  • Alternatively, we can use another package manager, Yarn.

Setting up our React app

To create our React app, we go to our terminal or command prompt, using the git cd command, we change the path to the directory we want our app to be created in.

1cd <name of the directory>

Then we run

1npx create-react-app <name of our app>

Running these commands scaffolds a React app out of the box. To start a development server on port 3000, we run the following command and navigate to localhost:3000 on our browser

1npm run start # or yarn start.

Installing dependencies

We’ll install required packages which are React Player and Framer motion.

React Player

React Player is a React library that enables us to play a variety of URLs, including file paths. With React Player, we can easily alter the properties of our video player and call callback functions depending on player events. It offers excellent media experience in web applications.

To install React Player in our app, we run the command.

1npm install react-player # or yarn add react-player

Framer Motion

Framer Motion is a React animation library that allows us to create animations quickly. It's easy to use syntax and even easier to understand documentation makes it an excellent fit for this project.

We run this command, to install Framer Motion in our app.

1npm install framer-motion

Creating the video player

First, we import the React Player into our App.js file.

1import React from 'react';
2 import ReactPlayer from 'react-player';

This ReactPlayer component comes with wide range of props that we pass values in to personalize our video player.

To start, we will use the url prop, the controls prop and finally, the playing prop.

The url prop’s value points to the url of the media we are looking to play. The controls prop, can be set to a boolean ( either true or false ), if set to true, the video player displays the native player controls, and if not it hides the controls. Lastly we have the playing prop, this prop is set to a boolean value, which if set to true, plays the media and if set to false, pauses the media.

We could also use the width and height prop to set the values for the width and height respectively of our video player. Failing to do so sets our video player to this default dimensions width: 640px; height: 360px; which we will use in this tutorial.

Seeing as we are trying to build a different webpage from the one we got when we initially created our React app, we replace the boilerplate code in the App.js file with this block of code below.

1// App.js
3 import React from 'react';
4 import ReactPlayer from 'react-player';
5 import './App.css';
7 const App= () => (
8 <div className="App">
9 <div className="player-wrapper">
10 <ReactPlayer
11 className = 'react-player'
12 url = ''
13 controls = {true}
14 playing = { true }
15 />
16 </div>
17 </div>
19 )
20 };
22 export default App;

Writing our React Player component, we pass in the path of our video as the value to the url prop, and set our controls and playing props to true. This plays the video on mount and displays the native player controls.

Now that we have our primary video player set up, we can start working on our overlay.

Creating the Overlay

Creating an overlay for our app requires a slight change in our file structure. To do that, we create a 'component' folder in our 'src' folder. This component folder will hold our 'video-overlay' folder. The 'video-overlay' folder will then contain our files' video-overlay. jsx' file and 'video-overlay.css' ( this is where we will write the styling for our overlay ).

1(project's root directory)
2 ├── node_modules
3 ├── public
4 ├── src
5 | ├── component
6 | | ├── video-overlay
7 | | | ├── video-overlay.css
8 | | | ├── video-overlay.jsx
9 | ├── _app.js
10 | └── index.js
11 ├── package-lock.json
12 ├── package.json
13 ├──
14 └── .gitignore

In the video-overlay.jsx file, we create the overlay we will use in this tutorial. A div containing the video's information and a play button is sufficient.

1{/* src/component/video-overlay/video-overlay.jsx */}
3 import React from 'react';
4 import './video-overlay.css';
6 const VideoOverlay = () => (
7 <div className= 'video-overlay-container'>
8 <div className= 'video-overlay'>
9 <h2>dépôt: tenant une fleur</h2>
10 <p>This is video is inspired by Netflix's Ui, and the title is in French, can you tell!. </p>
11 <button className= 'play-btn'>Play</button>
12 </div>
13 </div>
14 );
16 export default VideoOverlay;

Now that we have our overlay, we import it into our App.js file.

1import React, { useState } from "react";
2 import { useEffect } from "react";
3 import ReactPlayer from "react-player";
4 import VideoOverlay from "../video-overlay/video-overlay";
5 import "./video-player";
7 const App = () =>(
8 <div className="video-player">
9 <div className="player-wrapper">
10 <ReactPlayer
11 className="react-player"
12 url=""
13 controls= {true}
14 playing={true}
15 />
17 {/* This is the video overlay component we just created */}
18 <VideoOverlay/>
20 </div>
21 </div>
22 );
23 };

Our overlay is incomplete without the styling. Therefore, we define the style properties of our overlay in our video in our ‘video-overlay.css’ file.

The video overlay container houses the overlay with a height of 640px and a width of 360px. These are the measurement of the video player. Next, we set our video overlay’s position to absolute.

Any element ( in this case, <div className = 'video-overlay-container'></div> ) with a position absolute property, is positioned in relative to the element’s parent instead of the entire viewport. The element directly above it as we see below is the ‘player-wrapper’ div.

The top and bottom property tell us the distance from which we want our element to start. In this tutorial, we have our properties top and bottom set to 0, indicating that we wish our overlay to begin at the top of our video player and end at the bottom.

The actual overlay should only be half of the overlay-container, so we set the width property to 50% of the parent element. We give the overlay a background-color property background-color: rgba(0, 0, 0, 0.822). This value gives us a light black background.{
2 box-sizing: border-box;
3 width: 640px;
4 height: 360px;
5 position: absolute;
6 top: 0;
7 bottom: 0;
8 color: #fff;
9 font-family: 'Nunito Sans', sans-serif;
12 }
13 .video-overlay{
14 width: 50%;
15 height: 100%;
16 background-color: rgba(0, 0, 0, 0.822);
17 margin-top: 0;
18 text-align: left;
19 padding: 30px;
20 box-sizing: border-box;
22 }
23 .play-btn{
24 width: 90%;
25 height: 30px;
26 margin: 0 auto;
27 text-align: left;
28 }

Selectively playing the video and rendering the overlay

Three seconds after our video player is mounted, we want to play the video automatically. After five seconds, we want to remove the overlay.

To build that function into our video player, we define states using react hooks to control the different properties of the video and the video player.

In our App.js file, we import the useState and useEffect hooks from react.

1import React, { useState } from "react";
2 import { useEffect } from "react";
3 import ReactPlayer from "react-player";
4 import VideoOverlay from "../video-overlay/video-overlay";
5 import "./video-player";

In the block of code below, we define the states variables.

1const [overlay, showOverlay] = useState(true);
2 const [playing, setPlaying] = useState(false);
3 const [controls, setControls] = useState(false);

The overlay variable is set to an initial value of true, this variable will be used to selectively render our overlay. The controls and playing variables are set to an initial value of false. The controls variable will be used to set the controls prop on our React Player component, while the playing variable, the playing prop.

Next, we write out the functions that will affect these state variables.

1const onPlayMedia = () => {
2 setPlaying(true);
3 }
4 const onEndMedia = () => {
5 showOverlay(true)
6 setControls(false);
7 }
9 useEffect(() => {
10 setTimeout(() => {
11 setPlaying(true)
12 }, 3000);
14 }, [])
16 useEffect(() => {
17 setTimeout(() => {
18 showOverlay(false)
19 setControls(true)
20 }, 5000);
23 }, [])

The onPlayMedia function sets our playing variable to true. In contrast, the onEndMedia function sets our overlay variable to true and our control variable to false.

Another hook we get from react is the useEffect hook. The useEffect hook takes in as a parameter, a function and an array of dependencies.

Passing an empty array for the hook dependencies causes the functions in the useEffect hook to run only once when the app mounts.

In the code block above both, the useEffect hooks run a setTimeout function and have empty arrays for dependencies.

The first useEffect hook sets the playing variable to true after 3000ms ( 3s ). The second useEffect hook, sets our overlay variable to false and our control variable to true after 5000ms ( 5s ).

Lastly, we pass in these variables and functions as values to their respective React player props. The playing variable to the playing prop, and the controls variable to the controls prop.

1<div className="video-player">
2 <div className="player-wrapper">
3 <ReactPlayer
4 className="react-player"
5 url=""
6 controls={controls}
7 pip={true}
8 onPlay={onPlayMedia}
9 onEnded={onEndMedia}
10 playing={playing}
11 />
13 <VideoOverlay
14 onPlayMedia={onPlayMedia}
15 overlay={overlay}
16 />
17 </div>
18 </div>

The React Player allows for functions to be passed in as props. We take advantage of that by passing the onPlayMedia and onEndMedia function to the props onPlay and onEnd. The onPlay prop calls the function when the media starts playing and onEnd when the media ends.

Finally, we pass the onPlayMedia function as props into our 'VideoOverlay' component so that the play button on the overlay can play the video.

We also pass the overlay variable so that our 'Video-Overlay' component can be aware of when we want to mount or unmount the overlay in our app.

When we are done, our App component should look like this.

1const App = () => {
2 const [overlay, showOverlay] = useState(true);
3 const [playing, setPlaying] = useState(false);
4 const [controls, setControls] = useState(false);
6 const onPlayMedia = () => {
7 setPlaying(true);
8 }
9 const onEndMedia = () => {
10 showOverlay(true)
11 setControls(false);
12 }
14 useEffect(() => {
15 setTimeout(() => {
16 setPlaying(true)
17 }, 3000);
19 }, [])
21 useEffect(() => {
22 setTimeout(() => {
23 showOverlay(false)
24 setControls(true)
25 }, 5000);
28 }, [])
30 return (
31 <div className="video-player">
32 <div className="player-wrapper">
33 <ReactPlayer
34 className="react-player"
35 url=""
36 controls={controls}
37 pip={true}
38 onPlay={onPlayMedia}
39 onEnded={onEndMedia}
40 playing={playing}
41 />
43 <VideoOverlay
44 onPlayMedia={onPlayMedia}
45 overlay={overlay}
46 />
47 </div>
48 </div>
49 );
50 };
52 export default App;

Animating the overlay with Framer Motion

To use Framer Motion to animate elements in our app, we start by importing motion and AnimatePresence into the video-overlay.jsx file, containing the VideoOverlay component that we are looking to animate in and animate out.

1import { motion, AnimatePresence } from "framer-motion"

Framer Motion lets us define animation values in an object. We can then pass this object in as a prop to the component or element that needs to be animated ( in this case, the 'VideoOverlay' component ).

We define our animation object, variants, in the App.js file.

1const variants = {
2 hidden: {
3 opacity: 0
4 },
5 visible: {
6 opacity: 1,
7 transition: {
8 duration: 0.7
9 }
11 }
12 }

This object has two properties which are also objects, hidden ( what the initial value of the property of the element should be ) and visible ( what we want the element to be animated to ). In this case, we are animating the opacity property from 0 to 1 for a duration of 0.7seconds.

Next, we pass the variants object into our VideoOverlay component as a prop and assign it a prop name of variants. This way, our VideoOverlay component can access the object.

1<VideoOverlay onPlayMedia = {onPlayMedia} variants = {variants} overlay={overlay}/>

In the next step, we will be using this variant prop to animate our overlay.

Transitioning in and out

To animate any element in our app, we replace the HTML elements with motion elements. There is a motion element for every HTML and SVG element (e.g. <motion.div>, <motion.h2> ). These motion elements can accept several props, which allows us to add animations or define animation behaviors.

Framer Motion's AnimatePresence detects what elements are about to be unmounted, removed from our webpage and lets us animate them out.

In our 'video-overlay.jsx' file, we wrap our VideoOverlay component with the AnimatePresence component. Then, we check for the overlay property we received as prop from the App component and use it to render our overlay component selectively using the framer motion syntax.

1{/* src/component/video-overlay/video-overlay.jsx */}
3 import React from 'react';
4 import { motion, AnimatePresence } from "framer-motion"
5 import './video-overlay.css';
7 const VideoOverlay = ({onPlayMedia, variants, overlay }) => (
9 <AnimatePresence>
10 {
11 overlay && (
12 <motion.div className="video-overlay-container"
13 key = 'overlay'
14 initial = "hidden"
15 animate = "visible"
16 exit = {{opacity: 0}}
17 variants = {variants}
18 >
19 <div className= 'video-overlay'>
20 <h2>dépôt: tenant une fleur</h2>
21 <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Delectus, eos fugiat! Nam veritatis voluptatem fuga omnis dicta est molestias numquam fugiat odio maxime, sed veniam dolores rem iusto laudantium delectus!</p>
22 <button className= 'play-btn' onClick= {onPlayMedia}>Play</button>
23 </div>
24 </motion.div>
25 )
26 }
28 </AnimatePresence>
29 );
31 export default VideoOverlay;

We replaced the HTML div with Motion's div. Like any other Motion element, the <motion.div> has key-value pairs props that describe the animation's behaviour.

The initial prop, describes the initial properties of our element and is therefore set to the hidden value. The animate prop, describes the new properties we want our element to be animated to. It is set to visible. These values, hidden and visible, are accessed from the variants object.

The variants object is then passed as the value of the variants prop.

We use the exit prop to specify how the element should be animated out, which is opacity 0.

With these, we completed the development of the Netflix-styled animation on video overlays. Here’s what it looks like:


In this article, we created a video player with React Player. Then, we handled video playback transitions with the React animation library Framer Motion. With Framer Motion, we animated in and out our overlay after a given period depending on different player events.


You may also find the following resources necessary.

Emma Alder

Technical Writer at

Technical writer at