Friday, March 17, 2023
HomeCSSOptimising Largest Contentful Paint – CSS Wizardry – Net Efficiency Optimisation

Optimising Largest Contentful Paint – CSS Wizardry – Net Efficiency Optimisation

Written by on CSS Wizardry.

Desk of Contents
  1. Remedy All the things Beforehand
  2. Optimise Your LCP Candidate
  3. Keep away from Picture-Primarily based LCPs
  4. Use the Finest Candidate
    1. Demos
    2. <img> Components
      1. <image> and <supply />
    3. <picture> in <svg>
    4. <video> Components’ poster Attribute
    5. background-image: url();
      1. Getting Round background-image Points
    6. Abstract
  5. Don’t Shoot Your self within the Foot
    1. Don’t Lazy-Load Your LCP
    2. Don’t Fade-In Your LCP
    3. Don’t Host Your LCP Off-Web site
    4. Don’t Construct Your LCP on the Shopper
    5. Don’t Usurp Your Personal LCP
  6. Abstract

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:

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

Let’s go.

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
  • Redirects
  • TTFB
  • 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

is an unimaginable device for getting timings knowledge from CrUX.

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’s Largest Contentful Paint (LCP) web page, these

  • <img> parts
  • <picture> parts inside an <svg> component
  • <video> parts (the poster picture is used)
  • A component with a background picture loaded by way of the
    url() perform (as
    against a CSS
  • Block-level
    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-<head> JavaScript file so as to:

  1. exaggerate the waterfalls, and;
  2. 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:

The WebPageTest

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:

Be aware a bug in reported LCP with <picture> in
<svg>: extra on this later. (View full measurement.)

<img> and poster are equivalent in LCP; <picture> in <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.

A bug in Chrome ≤101 mistakenly stories a textual content node because the LCP
component. That is mounted in model 102.

As we will see, not all candidates are born equal. Let’s take a look at every in
extra element.

<img> Components

LCP candidate found instantly.

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.

<image> and <supply />

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
srcset and 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
preload scanner

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
<supply />, srcset, sizes to make use of, however that shall be mooted fairly shortly
by nearly another transferring half alongside the way in which.)

<picture> in <svg>

<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.

On the time of writing, there’s a bug in Chrome ≤101 wherein
the reported LCP comes again as not-the <picture> component. In
our demo, it’s truly flagged as being the a lot smaller
<p> component.

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.

This bug is mounted in Chrome 102.

Due to the present reporting bug, <picture> in <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 <picture> in <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> in

LCP candidate is hidden from the preload scanner.

<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
than finished…

<video> Components’ poster Attribute

I’m pleasantly shocked by the behaviour exhibited by the <video>’s poster
attribute. It appears to behave identically to the <img /> component, and is
found early by the preload scanner.

LCP candidate found instantly.

Which means 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.

background-image: url();

LCP candidate found when related DOM node is parsed (which is
blocked by synchronous JS).

Assets outlined in CSS (mainly something requested by way of the url()
) 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:

Which means background-image LCPs are requested on the final second,
which is way too late. We don’t like background-image LCPs.

Getting Round background-image Points

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;" />

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
if attainable.


In abstract:

  • text-based LCPs are virtually all the time going to be the quickest;
  • <img /> and poster LCPs are good and quick, discoverable by the preload
  • <video> with out a poster might need its first body thought of as an LCP
    candidate in future variations of Chrome;
  • <picture> in <svg> is at the moment misreported however is gradual as a result of the href
    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 <img />.

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
than the <img /> variant, and virtually equivalent to the background-image check.

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.

Be aware the picture arrives at 3.5s, but the LCP is reported at 4s.

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
. This
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.

N.B. Whereas 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
JavaScript. Ideally, a browser will obtain your HTML response, and the
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 defered 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:

View full measurement.

Be sure that your LCP candidate is what you count on it to be. Design modals and
cookie banners and many others. to:

  1. load instantly, and;
  2. 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.

View full measurement.

☕️ Did this assist? Purchase me a espresso!



Please enter your comment!
Please enter your name here

Most Popular

Recent Comments