Skip Navigation

Scott Spence

Create a Video Overlay with Hooks

• 2 min read
Hey! Thanks for stopping by! Just a word of warning, this post is 6 years old, wow! If there's technical information in here it's more than likely out of date.

Create a Video overlay with React hooks.

I had to create a video overlay for a project I was working on. This example use a portal to render the player with react-player.

1// useModal.js
2import { useState } from 'react';
3
4export const useModal = () => {
5	const [isShowing, setIsShowing] = useState(false);
6
7	const toggle = () => {
8		setIsShowing(!isShowing);
9	};
10
11	return {
12		isShowing,
13		toggle,
14	};
15};
1// VideoPlayer.js
2import React from 'react';
3import ReactPlayer from 'react-player';
4
5export const VideoPlayer = (props) => {
6	return (
7		<ReactPlayer
8			{...props}
9			url="https://www.youtube.com/watch?reload=9&v=YE7VzlLtp-4"
10			playing={props.playing}
11			controls
12			width="100%"
13			height="100%"
14			css={{
15				position: `absolute`,
16				top: 0,
17				left: 0,
18			}}
19		/>
20	);
21};
1// VideoModal.js
2import React from 'react';
3import ReactDOM from 'react-dom';
4import styled from 'styled-components';
5import closePrimary from '../../static/buttonClose.svg';
6import { VideoPlayer } from './VideoPlayer';
7
8const ModalOverlay = styled.div`
9	position: fixed;
10	top: 0;
11	left: 0;
12	width: 100vw;
13	height: 100vh;
14	background-color: darkgrey;
15	opacity: 0.5;
16`;
17
18const ModalWrapper = styled.div`
19	position: fixed;
20	top: 0;
21	left: 0;
22	outline: 0;
23	position: fixed;
24	top: 10vh;
25	bottom: 10vh;
26	left: 10vh;
27	right: 10vh;
28	display: flex;
29`;
30
31const ModalHeader = styled.div`
32	position: fixed;
33	top: 20px;
34	right: 20px;
35	padding: 1.5rem;
36	z-index: 1;
37`;
38
39const Modal = styled.div`
40	background: ${({ theme }) => theme.primary};
41	position: relative;
42	border-radius: 3px;
43	display: flex;
44	flex-direction: column;
45	flex: 1;
46`;
47
48const CloseButton = styled.div`
49	padding: 30px;
50	border-radius: 50%;
51	margin: -1rem -1rem -1rem auto;
52	cursor: pointer;
53	background-repeat: no-repeat;
54	background-image: url(${closePrimary});
55`;
56
57const PlayerWrapper = styled.div`
58	position: relative;
59	flex: 1;
60	padding: 50px 0;
61`;
62
63const PlayerSizer = styled.div`
64	width: 0;
65	height: 100%;
66	padding-right: 82%;
67	margin: 0 auto;
68`;
69
70export const VideoModal = ({ isShowing, hide }) =>
71	isShowing
72		? ReactDOM.createPortal(
73				<>
74					<ModalOverlay onClick={hide} />
75					<ModalWrapper
76						aria-modal
77						aria-hidden
78						tabIndex={-1}
79						role="dialog"
80					>
81						<Modal>
82							<ModalHeader>
83								<CloseButton
84									data-dismiss="modal"
85									aria-label="Close"
86									onClick={hide}
87								/>
88							</ModalHeader>
89							<PlayerWrapper>
90								<PlayerSizer>
91									<VideoPlayer playing={true} />
92								</PlayerSizer>
93							</PlayerWrapper>
94						</Modal>
95					</ModalWrapper>
96				</>,
97				document.body,
98			)
99		: null;

Then in the component:

1import React from 'react';
2import { VideoModal } from '../components/VideoModal';
3import { useModal } from '../hooks/useModal';
4import styled from 'styled-components';
5import playSvg from '../../static/playIcon.svg';
6
7const Wrapper = styled.div`
8	height: 100%;
9	display: flex;
10	align-items: center;
11	justify-content: center;
12`;
13
14const PlayDiv = styled.div`
15	/* margin: 0 auto; */
16	background-repeat: no-repeat;
17	height: 50px;
18	width: 50px;
19	background-image: url(${playSvg});
20`;
21
22export default () => {
23	const { isShowing, toggle } = useModal();
24	return (
25		<>
26			<Wrapper>
27				<VideoModal isShowing={isShowing} hide={toggle} />
28				{/* <button onClick={toggle}>Click This Button</button> */}
29				<PlayDiv onClick={toggle} />
30			</Wrapper>
31		</>
32	);
33};

There's a reactions leaderboard you can check out too.

Sign up for the newsletter

Want to keep up to date with what I'm working on?

Join other developers and sign up for the newsletter.

I care about the protection of your data. Read the Privacy Policy for more info.

Copyright © 2017 - 2026 - All rights reserved Scott Spence