Add a background video
Add an accessible background video from an MP4, WebM, HLS, or Mux source
Add a decorative video behind your page content. Start with an MP4 or WebM file, which browsers can play directly. If your video is delivered as HLS, use the HLS or Mux option below.
Recommended approach
Use BackgroundVideo with an MP4 or WebM URL. Put the video and poster inside a wrapper with aria-hidden="true" because both are decorative. Keep the heading, links, and other page content outside that wrapper.
Build the next great video experience
Compare source optionsimport { BackgroundVideo } from '@videojs/react/media/background-video';
export default function BasicUsage() {
return (
<section className="add-background-video-react-demo">
<div className="add-background-video-react-demo__visual" aria-hidden="true">
<img className="add-background-video-react-demo__poster" src="https://image.mux.com/601n4w1fq88NJiVpzvrQQeQfNnnjjfKMIN7dCGAEarTs/thumbnail.webp" alt="" />
<BackgroundVideo className="add-background-video-react-demo__media" src="https://stream.mux.com/601n4w1fq88NJiVpzvrQQeQfNnnjjfKMIN7dCGAEarTs/highest.mp4" />
</div>
<div className="add-background-video-react-demo__content">
<h3>Build the next great video experience</h3>
<a href="#common-variations">Compare source options</a>
</div>
</section>
);
}
.add-background-video-react-demo {
position: relative;
display: grid;
min-height: 18rem;
overflow: hidden;
color: white;
background: black;
border-radius: 0.5rem;
isolation: isolate;
}
.add-background-video-react-demo__visual,
.add-background-video-react-demo__poster,
.add-background-video-react-demo__media {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.add-background-video-react-demo__visual {
pointer-events: none;
}
.add-background-video-react-demo__visual::after {
position: absolute;
inset: 0;
content: "";
background: linear-gradient(90deg, rgb(0 0 0 / 85%), rgb(0 0 0 / 55%));
}
.add-background-video-react-demo__poster,
.add-background-video-react-demo__media {
display: block;
object-fit: cover;
}
.add-background-video-react-demo__media {
--media-object-fit: cover;
--media-object-position: center;
}
.add-background-video-react-demo__content {
position: relative;
z-index: 1;
display: grid;
gap: 1rem;
place-content: end start;
max-width: 28rem;
padding: 2rem;
}
.add-background-video-react-demo__content h3 {
margin: 0;
font-size: 1.75rem;
line-height: 1.1;
}
.add-background-video-react-demo__content a {
width: fit-content;
padding: 0.625rem 1rem;
color: black;
text-decoration: none;
background: white;
border-radius: 0.25rem;
}
.add-background-video-react-demo__content a:focus-visible {
outline: 0.2rem solid white;
outline-offset: 0.2rem;
}
@media (prefers-reduced-motion: reduce) {
.add-background-video-react-demo__media {
display: none;
}
}
Build the next great video experience
Compare source options<section class="add-background-video-html-demo">
<div class="add-background-video-html-demo__visual" aria-hidden="true">
<img class="add-background-video-html-demo__poster" src="https://image.mux.com/601n4w1fq88NJiVpzvrQQeQfNnnjjfKMIN7dCGAEarTs/thumbnail.webp" alt="" />
<background-video
class="add-background-video-html-demo__media"
src="https://stream.mux.com/601n4w1fq88NJiVpzvrQQeQfNnnjjfKMIN7dCGAEarTs/highest.mp4"
></background-video>
</div>
<div class="add-background-video-html-demo__content">
<h3>Build the next great video experience</h3>
<a href="#common-variations">Compare source options</a>
</div>
</section>
.add-background-video-html-demo {
position: relative;
display: grid;
min-height: 18rem;
overflow: hidden;
color: white;
background: black;
border-radius: 0.5rem;
isolation: isolate;
}
.add-background-video-html-demo__visual,
.add-background-video-html-demo__poster,
.add-background-video-html-demo__media {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.add-background-video-html-demo__visual {
pointer-events: none;
}
.add-background-video-html-demo__visual::after {
position: absolute;
inset: 0;
content: "";
background: linear-gradient(90deg, rgb(0 0 0 / 85%), rgb(0 0 0 / 55%));
}
.add-background-video-html-demo__poster,
.add-background-video-html-demo__media {
display: block;
object-fit: cover;
}
.add-background-video-html-demo__media {
--media-object-fit: cover;
--media-object-position: center;
}
.add-background-video-html-demo__content {
position: relative;
z-index: 1;
display: grid;
gap: 1rem;
place-content: end start;
max-width: 28rem;
padding: 2rem;
}
.add-background-video-html-demo__content h3 {
margin: 0;
font-size: 1.75rem;
line-height: 1.1;
}
.add-background-video-html-demo__content a {
width: fit-content;
padding: 0.625rem 1rem;
color: black;
text-decoration: none;
background: white;
border-radius: 0.25rem;
}
.add-background-video-html-demo__content a:focus-visible {
outline: 0.2rem solid white;
outline-offset: 0.2rem;
}
@media (prefers-reduced-motion: reduce) {
.add-background-video-html-demo__media {
display: none;
}
}
import '@videojs/html/media/background-video';
How it works
BackgroundVideo renders the browser’s <video> element and starts it muted, looped, autoplaying, and inline. The example puts that video and an empty-alt poster in the .hero-visual wrapper. The wrapper is hidden from assistive technology and ignores pointer input, so it does not act like a media player.
The page defines the hero’s size. The video fills that space with --media-object-fit: cover, while the poster remains visible until the video paints a frame. The reduced-motion rule hides the video and leaves the poster in place.
Set the size, position, and transforms on the .hero-visual wrapper so the poster and video stay together.
Availability and constraints
- Use a source the browser can play directly, such as MP4 or WebM.
- Safari can play HLS URLs directly. Other browsers cannot do so reliably, so use an HLS variation below when the same
.m3u8URL must work across browsers. - BackgroundVideo does not create a poster or report analytics. Keep the poster in your page and add analytics only when you need them.
- Video.js does not apply a reduced-motion policy for you. The example stops the decoration with
prefers-reduced-motion. - If the video communicates information, remove
aria-hidden, give it an accessible name and controls, and use a regular video player.
Common variations
Choose a variation based on the source you already have:
| Need | Use |
|---|---|
| Cross-browser HLS with a small background-only player | HlsBackgroundVideo |
| The same background-only player for a Mux HLS URL | MuxBackgroundVideo |
Play an HLS video
HlsBackgroundVideo plays an HLS video without adding controls, audio, or captions. Pass a complete HLS URL through src:
import { HlsBackgroundVideo } from '@videojs/react/media/hls-background-video';
<HlsBackgroundVideo
className="hero-media"
src="https://media.example.com/hero.m3u8"
crossOrigin="anonymous"
onError={() => console.error('The background stream could not play')}
/><script type="module">
import '@videojs/html/media/hls-background-video';
</script>
<hls-background-video
class="hero-media"
src="https://media.example.com/hero.m3u8"
crossorigin
></hls-background-video>Your HLS stream must be unencrypted and use fragmented MP4 video segments, also called fMP4 or CMAF. The component chooses one video size when playback starts and does not switch sizes later. It cannot play older MPEG-TS segments.
Play a Mux HLS URL
MuxBackgroundVideo is a Mux-named alias for HlsBackgroundVideo. Pass a complete Mux HLS URL, not a bare playback ID or source object:
import { MuxBackgroundVideo } from '@videojs/react/media/mux-background-video';
<MuxBackgroundVideo
className="hero-media"
src="https://stream.mux.com/PLAYBACK_ID.m3u8?max_resolution=720p"
crossOrigin="anonymous"
/><script type="module">
import '@videojs/html/media/mux-background-video';
</script>
<mux-background-video
class="hero-media"
src="https://stream.mux.com/PLAYBACK_ID.m3u8?max_resolution=720p"
crossorigin
></mux-background-video>This component does not create a Mux poster, preview thumbnails, or analytics session. Keep the poster in your page and add analytics separately when you need them.
Troubleshooting
An HLS URL works in Safari but not another browser
BackgroundVideo hands its src to the browser’s <video> element. Use HlsBackgroundVideo for a supported fMP4 HLS source, or MuxBackgroundVideo for a Mux HLS URL.
The video does not fill or follow transforms
Set the size, transforms, and measurements on the wrapper that contains the video and poster. Size the background-video component to fill that wrapper.
No poster or Mux analytics appear
The background-video components do not provide them. Render an empty-alt poster in the same wrapper as the video, and add analytics separately.