
[Resolved] Safari broke my background video
My hero background video worked in Chrome, Edge, and Firefox, but Safari made it load inconsistently. The fix was a Safari fallback using a wrapper div and CSS background-image.
By Suryansh Kushwaha /
On this page
A few days after launching my website, I found a Safari-specific issue in the hero section.
The background video worked in Chrome, Edge, and Firefox. In Safari, it was inconsistent. Sometimes it played, sometimes it took too long to load, and sometimes the first viewport looked unfinished.
The video file was valid. The path was correct. The usual autoplay attributes were already present.
<video class="hero-video" autoplay muted loop playsinline>
<source src="/hero-video.mp4" type="video/mp4" />
</video>That setup is normally enough for a decorative background video:
autoplaystarts the video automaticallymutedallows autoplay in modern browsersloopkeeps the background movingplaysinlineprevents mobile Safari from opening fullscreen playback
Safari still did not behave reliably.
The Fix
The solution was to add a fallback layer behind the normal <video> element.
The fallback is a wrapper div that uses the same .mp4 file as a CSS
background-image.
I found this approach through a Webflow forum trail that pointed to
Avinash Kumar's Safari background video write-up.
It looks unusual, but Safari can render video media through background-image,
which makes it useful as a fallback for this specific issue.
<section class="hero">
<div class="hero-video-fallback" aria-hidden="true"></div>
<video
class="hero-video"
autoplay
muted
loop
playsinline
preload="metadata"
poster="/hero-poster.jpg"
aria-hidden="true"
>
<source src="/hero-video.mp4" type="video/mp4" />
</video>
<div class="hero-content">
<h1>Your hero content</h1>
</div>
</section>.hero {
position: relative;
min-height: 100vh;
overflow: hidden;
}
.hero-video-fallback,
.hero-video {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.hero-video-fallback {
background-image: url('/hero-video.mp4');
background-position: center;
background-size: cover;
}
.hero-video {
object-fit: cover;
}
.hero-content {
position: relative;
}The normal video element continues to work in browsers that handle it well. Safari has the fallback layer available when the video element is unreliable.
React / Next.js Note
In React and Next.js, use playsInline instead of playsinline.
<video
autoPlay
muted
loop
playsInline
preload='metadata'
poster='/hero-poster.jpg'
aria-hidden='true'
>
<source src='/hero-video.mp4' type='video/mp4' />
</video>Small casing issue, very easy to miss.
Production Checklist
If a Safari background video is unreliable, I would check these first:
- Open the video file directly in Safari and confirm it loads.
- Add
muted,autoplay,loop, andplaysinline. - Use
playsInlinewhen writing JSX. - Add a
posterimage. - Keep the video short and compressed.
- Check parent stacking, overlays, and
overflowrules. - Add the wrapper fallback with
background-image: url('/video.mp4'). - Test desktop Safari and mobile Safari separately.
The fallback does not fix a heavy or badly encoded video. It only gives Safari a more reliable rendering path for this background-video use case.
Final Takeaway
For background videos, do not rely only on the <video> element if the first
viewport matters.
Use the normal video tag, keep the correct autoplay attributes, add a poster, and give Safari a wrapper-based fallback.
That made the hero section reliable for me.
If you want this kind of browser testing and reliability handled properly for your own website, check out my Studio and send me a request. ;)