A hero video earns its place on a landing page. Motion above the fold makes a static layout feel alive, and most themes and page builders now reduce the whole thing to a checkbox in the header settings. You choose an MP4, tick autoplay, and the section fills with movement.
The cost shows up in Lighthouse the day it ships. Open PageSpeed Insights on that page and read the element Chrome names as Largest Contentful Paint. On a hero section it is rarely what the designer had in mind, and the first instinct is to compress the video harder. That usually moves the number by nothing at all.
A background video is above the fold by definition, so it competes with the one paint Google measures. This covers how to find the element Chrome is timing on your page, and why the poster is the asset to work on rather than the video. It also covers the two attributes browsers require before they autoplay anything, what to send a phone instead, and how to keep the player off the critical path.
TL;DR
Chrome measures the largest element painted in the viewport. In a hero section four things can win that: the poster image, the first painted video frame, the headline text block, and a CSS background image. Find out which one applies to your page before you change any markup.
In most builds the lever is the poster: sized to the box it renders in, saved in a modern format, preloaded with high priority, and never lazy loaded. muted and playsinline are browser requirements rather than preferences. An explicit aspect ratio keeps the late player out of CLS.
Find out which element Chrome is measuring on your hero
The general rule is simple enough to state. Chrome picks the largest element painted in the viewport as the page loads, revises that pick as bigger things paint, and stops at the first user interaction. What makes a hero awkward is that several candidates sit in the same box.
| Candidate | When it tends to win | What you control |
|---|---|---|
| Poster image on the <video> | The poster paints before the video decodes, which is the common case | Dimensions, format, fetch priority |
| First painted video frame | Autoplay starts early and nothing larger paints first. Chrome began treating video frames as LCP candidates during 2023 | Very little. Decode time is the gate |
| Headline text block | The media is a CSS background, or the video box is small | Font loading and font display |
| CSS background image | The hero uses background-image rather than a <video> | Size, format and priority, as with any image |
Three ways to get the answer, in order of effort. Run PageSpeed Insights and read the Largest Contentful Paint element under Diagnostics, which names the node directly. Record a load in the Chrome DevTools performance panel and hover the LCP marker in the timings track. For real visits rather than a lab run, the attribution build of Google's web-vitals library reports the element selector with the timing.
Do that first. A hero built on a CSS background image has a different fix from one built on a <video> tag.
Work on the poster, because that is the asset you actually control
When the poster wins the measurement, it is the whole job. Four moves matter, and none involve the video file.
Size it to the box it renders in. A 3840 pixel wide still dropped into a 1440 pixel container spends most of its bytes on pixels nobody sees. Measure the rendered width at your largest breakpoint, double it for high density screens, and stop there.
Save it in a modern format. WebP and AVIF both cut a photographic still below the equivalent JPEG at the same perceived quality. WebP vs PNG covers where each format earns its place.
Raise its priority in the head. The fetchpriority attribute applies to img, link, script and iframe elements, and the poster attribute on a <video> is none of those. So you preload it instead.
<link rel="preload"
as="image"
href="/wp-content/uploads/2026/09/hero-poster.webp"
fetchpriority="high">Never lazy load it. A loading="lazy" attribute on the hero image is the most common self-inflicted LCP regression in WordPress, because several optimisation plugins apply it to every image by default. Check the rendered HTML rather than the plugin settings, and add the hero to the exclusion list.
Generating that still by hand means a frame grab per video, a resize per breakpoint and a file to keep in sync. On the FastPix block and shortcode, poster takes a URL you supply and wins over thumbnailtime, which names the second used for the still. The default is second one, which on a clip that fades in from black is the wrong frame to be measured on.
Google's good threshold for Largest Contentful Paint is 2.5 seconds or less, assessed at the 75th percentile of real visits.
muted and playsinline are browser requirements, not preferences
Two attributes decide whether your hero plays at all, and both get treated as styling choices in theme documentation.
Browsers block autoplay with sound unless the visitor has already interacted with the site, or has built enough engagement with the domain. Without muted in the markup, the play() promise is rejected and the hero sits frozen on its poster. Setting video.muted = true after calling play() is too late, because the decision was made when the call was evaluated.
Without playsinline, iOS Safari takes the video fullscreen the moment it starts. On an iPhone that turns a background flourish into a full screen takeover, which is worse than the video never playing.
<section class="hero">
<video class="hero__video"
poster="/wp-content/uploads/2026/09/hero-poster.webp"
width="1920" height="1080"
autoplay muted playsinline loop
preload="none">
<source src="/wp-content/uploads/2026/09/hero-1080.mp4" type="video/mp4">
</video>
<h1 class="hero__headline">Your headline sits here</h1>
</section>Note preload="none" alongside autoplay. The browser still fetches what it needs to start playing, and the hint keeps it from pulling the whole file ahead of assets the page needs first. The FastPix shortcode carries the same set as named parameters, so a hero embed reads [fastpix id="…" autoplay muted loop nocontrols], with muted documented as a browser requirement rather than a volume preference.
Reserve the box before the player draws into it
A hero with no height until its player initialises pushes the headline and everything under it down the page when it arrives. That is Cumulative Layout Shift, and Google's good threshold is 0.1 or less at the 75th percentile.
.hero__video {
aspect-ratio: 16 / 9;
width: 100%;
height: auto;
display: block;
object-fit: cover;
}Width and height attributes do the same job for a plain <video>, because the browser derives the ratio from them before any bytes arrive. A third-party embed that builds its own DOM needs the ratio on the container instead. The FastPix embed takes aspectratio, which forces a ratio such as 16:9 rather than waiting to discover the video's own. Optimize video player layouts for any screen size covers the responsive side.
On a phone, send a still instead of a stream
This decision deserves an argument rather than a rule.
A background video is decoration. It carries no information the page would lose without it, which is why it autoplays muted and loops. On a phone, that decoration spends somebody's data plan on content they did not choose to watch. The decode also competes with the main thread while the page is still becoming interactive, which is where Interaction to Next Paint damage begins.
Set against that, the design intent usually survives a good still. Motion in a hero is atmosphere. A well chosen frame from the same clip, with the same grade and composition, reads as the same design at a fraction of the weight.
The same switch covers accessibility. A visitor who has set prefers-reduced-motion has asked for exactly this.
One implementation warning. Hiding the video with display: none in a media query does not reliably stop the browser fetching the source, so the bytes can still cross the network for a hero nobody sees. Gate it in the markup or in script instead.
Keep the player off the critical path
Lazy loading is the usual answer to a heavy embed, and it does nothing for a hero. The element is already in the viewport at load, so an observer fires immediately and no work is deferred. Guide to lazy loading HTML videos covers the mechanism, and why video makes a WordPress site slow covers the players below the fold, where it does pay.
What defers a hero is splitting the poster from the player. Ship the still as a real <img> in the HTML, then attach the video after the load event, on the devices that should get it.
<div class="hero__media" data-hero-src="/wp-content/uploads/2026/09/hero-1080.mp4">
<img class="hero__poster" src="/wp-content/uploads/2026/09/hero-poster.webp"
alt="" width="1920" height="1080" fetchpriority="high">
</div>
<script>
addEventListener('load', function () {
var box = document.querySelector('[data-hero-src]');
if (!box) return;
if (!matchMedia('(min-width: 768px)').matches) return;
if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;
var v = document.createElement('video');
v.src = box.dataset.heroSrc;
v.className = 'hero__video';
v.autoplay = v.muted = v.loop = v.playsInline = true;
box.appendChild(v);
});
</script>Three things fall out of that shape. The LCP element is now an <img> you chose, so fetchpriority="high" applies directly. The mobile and reduced-motion decisions live in one place rather than across CSS. And the video never enters the network queue on a device that was never going to show it.
A hosted player adds one more hop, because it arrives from a third-party domain and costs a DNS lookup and a TLS handshake before its code runs. The FastPix player ships inside the plugin, so nothing is fetched from a remote server at render time. Understanding video player size and performance covers what a bundle costs once it loads. On the FastPix embed, lazyload defaults to true, which is right below the fold and changes nothing for a hero already in view.
Run PageSpeed on your hero, then change one thing
Open PageSpeed Insights on the hero page and write down two numbers and one name: the LCP value, the CLS value, and the element the report identifies. That name tells you whether the rest of this article applies, or whether you have a font loading problem wearing a video costume.
Then change the poster alone. Resize it to the rendered box, save it as WebP or AVIF, preload it with high priority, and confirm no plugin has added loading="lazy". Re-run the report and compare the same three values.
On a FastPix embed, the poster, the aspect ratio and the autoplay attributes are parameters on one shortcode, so that pass is a single edit rather than a theme patch. The free plan covers 10 videos with no card, which is more than one landing page needs.
Frequently Asked Questions (FAQs)
Is a background video the LCP element on a WordPress page?
Sometimes, and it is not worth guessing. Four things in a hero can win: the poster, the first painted video frame, the headline text block, and a CSS background image. Chrome picks whichever is largest in the viewport. Run PageSpeed Insights and read the element it names.
Why does compressing my hero video not improve LCP?
Because the video file is usually not what is being timed. If the poster wins the measurement, LCP is settled long before the video has downloaded enough to play. Compressing it still helps the data bill and the decode cost on a phone, and it is not the LCP lever.
Do I need muted and playsinline on a WordPress background video?
Yes, both. Browsers block autoplay with sound unless the visitor has already interacted with the site. Without muted the play call is rejected, and the hero sits frozen on its poster. Without playsinline, iOS Safari takes the video fullscreen on play.
Should I show a background video on mobile?
Usually not. A background video is decoration, so on a phone it spends the visitor's data on something they did not ask to watch. The decode also competes with the main thread. Gate it in markup or script, because hiding it with CSS does not reliably stop the fetch.
How do I stop a hero video causing layout shift?
Reserve the box before anything draws into it, with width and height attributes on the element or an explicit aspect-ratio on the container. Google's good threshold for Cumulative Layout Shift is 0.1 or less at the 75th percentile.
Does lazy loading help a hero video?
No. A hero is already in view when the page loads, so the observer fires immediately. Lazy loading the poster is worse, because it delays the element Chrome is measuring. It belongs below the fold, which why video makes a WordPress site slow covers.
Can I use fetchpriority on a video poster?
Not directly. The attribute applies to img, link, script and iframe, and a poster attribute is none of those. Preload it instead, with as="image" and fetchpriority="high".








