Written by Harry Roberts on CSS Wizardry.
Desk of Contents
- Remedy All the things Beforehand
- Optimise Your LCP Candidate
- Keep away from Picture-Primarily based LCPs
- Use the Finest Candidate
- Don’t Shoot Your self within the Foot
Largest Contentful Paint (LCP) is my favorite Core Net
Important. It’s the best to optimise, and it’s the one one of many three that
works the very same within the lab because it does within the subject (don’t even get me
began on this…). But, surprisingly, it’s the least optimised CWV in CrUX—at
the time of writing, solely half of origins within the dataset had a Good LCP:
As soon as extra, we noticed an
enhance within the variety of origins having good Core Net Vitals (CWV) pushed by
improved good CLS.
52.7% of origins had good LCP
94.9% of origins had
70.6% of origins had good CLS
39.0% of origins had good LCP, FID,
— Chrome UX Report 📊 (@ChromeUXReport) 8 March
This genuinely surprises me, as a result of LCP is the best metric to enhance. So,
on this submit, I wish to go deep and present you some fascinating methods and
optimisations, in addition to some pitfalls and bugs, beginning with some quite simple
Remedy All the things Beforehand
Let’s begin with the simple stuff. LCP is a milestone timing—it measures…
…the render time of the most important picture or textual content block seen inside the
viewport, relative to when the web page first began loading.
The necessary factor to notice right here is that Google doesn’t care the way you get to LCP,
so long as you get there quick. There are a variety of different issues that might occur
between the beginning of the web page load lifecycle and its LCP. These embrace (however are
not restricted to):
- DNS, TCP, TLS negotiation
- First Paint
- First Contentful Paint
If any of those are gradual, you’re already on the again foot, they usually’re going to
have a knock-on impact in your LCP. The metrics above don’t matter in and of
themselves, nevertheless it’s going to assist your LCP if you will get them as little as
An analogy I take advantage of with non-technical stakeholders goes a bit of like this:
It’s essential to get the children to high school for 08:30. That’s all the college cares
about—that the children are there on time. You are able to do loads to assist make this
occur: put together their garments the night time earlier than; put together their lunches the night time
earlier than (do the identical for your self). Set acceptable alarms. Have a morning
routine that everybody follows. Go away the home with loads of time to spare.
Plan in appropriate buffer time for visitors points, and many others.
The varsity doesn’t care when you laid out uniforms the night time earlier than. You’re being
judged in your capability to get the children to high school on time; it’s simply frequent sense
to do as a lot as you possibly can to make that occur.
Similar together with your LCP. Google doesn’t (at the moment) care about your TTFB, however an excellent
TTFB goes to assist get nearer to an excellent LCP.
Optimise the complete chain. Be sure you get all the things beforehand as quick as
attainable so that you just’re arrange for achievement.
Optimise Your LCP Candidate
A tip that hopefully doesn’t want me to enter any actual element: if in case you have an
image-based LCP, ensure that it’s nicely optimised—appropriate format, appropriately
sized, sensibly compressed, and many others. Don’t have a 3MB TIFF as your LCP candidate.
Keep away from Picture-Primarily based LCPs
This isn’t going to work for lots, if not most, websites. However the easiest way to get
a quick LCP is to make sure that your LCP is text-based. This, in impact, makes your
FCP and LCP synonymous. That’s it. So simple as that. If attainable, keep away from
image-based LCP candidates and decide as a substitute for textual LCPs.
The possibilities are, nevertheless, that gained’t give you the results you want. Let’s take a look at our different
Use the Finest Candidate
Okay. Now we’re moving into the enjoyable stuff. Let’s take a look at which LCP candidates
we’ve, and whether or not there are any relative deserves to every.
There are a number of potential candidates in your LCP. Taken straight from
internet.dev’s Largest Contentful Paint (LCP) web page, these
<picture>parts inside an
<video>parts (the poster picture is used)
- A component with a background picture loaded by way of the
against a CSS
parts containing textual content nodes or different inline-level textual content parts kids.
For the needs of this text, I constructed a sequence of decreased demos exhibiting how
every of the LCP sorts behave. Every of the demos additionally incorporates a reference to
a blocking in-
- exaggerate the waterfalls, and;
- stall the parser to see if or how every LCP kind is impacted by the preload
It’s additionally value noting that every demo may be very stripped again, and doesn’t
essentially symbolize real looking situations wherein many responses can be
in-flight on the identical time. As soon as we run into useful resource rivalry, LCP
candidates’ discovery may match in a different way to what’s exhibited in these decreased
check circumstances. In circumstances like these, we would look to Precedence
Preload to assist. All I’m
interested by proper now could be inherent variations in how browsers deal with sure
The preliminary demos will be discovered at:
is on the market so that you can look by way of, although we’ll decide aside particular person
waterfalls later within the article. That each one comes out wanting like this:
poster are equivalent in LCP;
<svg> is the
subsequent quickest, though there’s a bug within the LCP time that Chrome stories;
background-image-based LCPs are notably the slowest.
As we will see, not all candidates are born equal. Let’s take a look at every in
Of the image-based LCPs, that is in all probability our favorite.
<img> parts, as
lengthy as we don’t mess issues up, are fast to be found by the preload
and as such, will be requested in parallel to previous—even blocking—sources.
It’s value noting that the
<image> component behaves the identical manner because the
<img component. For this reason it is advisable to write a lot verbose syntax in your
sizes attributes: the concept is that you just give the browser sufficient
details about the picture that it might probably request the related file by way of the
and never have to attend till format. (Though, I suppose—technically—there have to be
like just a few milliseconds compute overhead understanding which mixture of
sizes to make use of, however that shall be mooted fairly shortly
by nearly another transferring half alongside the way in which.)
<picture> parts outlined in
<svg>s show two very fascinating behaviours.
The primary of which is a straightforward bug wherein Chrome misreports the LCP candidate,
seemingly overlooking the
<picture> completely. Relying in your context, this
might imply far more beneficial and optimistic LCP scores.
As soon as the repair rolls out in M102 (which is Canary on the time of writing, and can
attain Steady on 24 Might, 2022), we
can count on correct measurements. This does imply that you could be expertise
degraded LCP scores in your website.
Due to the present reporting bug,
<svg> is more likely to go from
being (inadvertently) one of many quickest LCP sorts, to one of many slowest. In
the unlikely occasion that you’re utilizing
<svg>, it’s in all probability
one thing that you just wish to verify on sooner somewhat than later—your scores are
more likely to change.
The bug pertains solely to reported LCP candidate, and doesn’t affect how the
browser truly offers with the sources. To that finish, waterfalls in all Chrome
variations look equivalent, and networking/scheduling behaviour stays unchanged.
Which brings me onto the second fascinating factor I noticed with
<picture> parts outlined in
<svg>s look like hidden from the preload
scanner: that’s to say, the
href attribute just isn’t parsed till the browser’s
major parser encounters it. I can solely guess that that is just because the
preload scanner is constructed to scan HTML and never SVG, and that that is by design
somewhat than an oversight. Maybe an optimisation that Chrome might make is to
preload scan embedded SVG in HTML…? However I’m positive that’s far more simply mentioned
I’m pleasantly shocked by the behaviour exhibited by the
attribute. It appears to behave identically to the
<img /> component, and is
found early by the preload scanner.
poster LCPs are inherently fairly quick, in order that’s good
The opposite information is that it seems like there’s intent to take the primary body of
a video because the
LCP candidate if no
poster is current. That’s going to be a troublesome LCP to
get below 2.5s, so both don’t have a
<video> LCP in any respect, or be sure you
begin utilizing a
poster picture with it.
Assets outlined in CSS (mainly something requested by way of the
perform) are gradual by
default. The most typical candidates listed here are background photos and internet fonts.
The rationale these sources (on this particular case, background photos) are gradual
is as a result of they aren’t requested till the browser is able to paint the DOM
node that wants them. You possibly can learn extra about that on this Twitter thread:
Easy but vital
factor all builders ought to consider: CSS sources (fonts, background
photos) aren’t requested by your CSS, however by the DOM node that wants them
[Note: slight oversimplification, but the correct way to think about
— Harry Roberts (@csswizardry) 10 September
background-image LCPs are requested on the final second,
which is way too late. We don’t like
If you happen to at the moment have a website whose LCP is a
background-image, you is perhaps
pondering of refactoring or rebuilding that part proper now. However, fortunately,
there’s a really fast workaround that requires virtually zero effort: let’s
complement the background with a hidden
<img /> that the browser can uncover
a lot earlier.
<div type="background-image: url(lcp.jpg)"> <img src="lcp.jpg" alt="" width="0" top="0" type="show: none !necessary;" /> </div>
This little hack permits the preload scanner to choose up the picture, somewhat than
ready till the browser is about to render the
<div>. This got here in 1.058s
quicker than the naive
background-image implementation. You’ll discover that this
waterfall virtually precisely mimics the quickest
<img /> choice:
We might additionally
preload this picture, somewhat than utilizing an
<img /> component, however
I typically really feel that
preload is a little bit of a code odor and must be averted
- text-based LCPs are virtually all the time going to be the quickest;
posterLCPs are good and quick, discoverable by the preload
<video>with out a
postermight need its first body thought of as an LCP
candidate in future variations of Chrome;
<svg>is at the moment misreported however is gradual as a result of the
is hidden from the preload scanner;
background-images are gradual by default, due to how CSS works;
- we will sidestep this difficulty by including an invisible
- we will sidestep this difficulty by including an invisible
Alright! Now we all know that are the very best candidates, is there anything can
do (or keep away from doing) to ensure we aren’t operating slowly? It turns on the market
are loads of issues that people do which inadvertently maintain again LCP scores.
Don’t Lazy-Load Your LCP
Each time I see this, my coronary heart sinks a bit of. Lazy-loading your LCP is
fully counter-intuitive. Please don’t do it!
Curiously, one of many options of
loading="lazy" is that it hides the
picture in query from the preload
Which means, even when the picture is within the viewport, the browser will nonetheless
late-request it. For this reason you possibly can’t safely add
loading="lazy" to all of
your photos and easily hope the browser does (what you suppose is) the proper
In my exams, lazily loading our picture pushed LCP again to 4.418s: 1.274s slower
<img /> variant, and virtually equivalent to the
Don’t Fade-In Your LCP
Predictably, fading in our picture over 500ms pushes our LCP occasion again by 500ms.
Chrome takes the top of the animation interval because the LCP measurement, transferring us
to a 3.767s LCP occasion somewhat than 3.144s.
Keep away from fading in your LCP candidate, whether or not it’s image- or text-based.
Don’t Host Your LCP Off-Web site
The place attainable, we should always all the time self-host our static
consists of our LCP candidate.
It’s not unusual for website house owners to make use of third-party picture optimisation companies
corresponding to Cloudinary to serve each automated and
dynamically optimised photos: on the fly resizing, format switching,
compression, and many others. Nevertheless, even when considering the efficiency
enhancements of of those companies, the price of heading to a distinct origin
virtually all the time outweighs the advantages. In
the time spent resolving a brand new origin added 509ms to general time spend
downloading our LCP picture.
By all means, use third occasion companies for non-critical, non-LCP photos, but when
you possibly can, convey your LCP candidate onto the identical origin because the host web page. That’s
precisely what I do for this website.
preconnect could assist a bit of, it’s nonetheless extremely unlikely
to be quicker than not opening a brand new connection in any respect.
Don’t Construct Your LCP on the Shopper
I see this all too usually, and it’s a part of the continued obsession with
reference to the LCP candidate (ideally an
<img /> component) shall be proper
there instantly. Nevertheless, when you construct your LCP candidate with JS, the method
is way, far more drawn out.
Constructing your LCP candidate in JS might vary from a easy JS-based
picture gallery, proper the way in which by way of to a totally client-rendered web page. The beneath
waterfall exhibits the latter:
The primary response is the HTML. What we’d wish to have is an
<img /> proper
there within the markup, ready to be found virtually instantly. As a substitute, the
HTML requests a
framework.js at entry 12. This, in flip, finally
requests API knowledge concerning the present product, at entry 50. This response incorporates
details about associated product imagery, which is finally put into the
digital DOM as an
<img />, lastly initiating a request for the LCP candidate
at entry 53, nicely over 7s into the web page load lifecycle.
Don’t Usurp Your Personal LCP
This one breaks my coronary heart each time I see it… Don’t late-load any content material that
by accident turns into your LCP candidate. Often, these are issues like cookie
banners or e-newsletter modals that cowl content material and get flagged as a really late
LCP. I mocked up a late-loading modal for our exams, and what’s necessary to
bear in mind is that the rating is correct, simply not what we hope for:
Be sure that your LCP candidate is what you count on it to be. Design modals and
cookie banners and many others. to:
- load instantly, and;
- not truly be your largest piece of content material.
Alright. We lined quite a bit there, however the takeaway is fairly easy:
text-based LCPs are the quickest, however unlikely to be attainable for many. Of
the picture primarily based LCP sorts,
<img /> and
poster are the quickest.
<picture>s outlined in
<svg>s are gradual as a result of they’re hidden from the
preload scanner. Past that, there are a number of issues that we have to keep away from:
don’t lazy load your LCP candidate, and don’t construct your LCP in JS.