Thursday, June 13, 2024
HomeCSSOptimising Largest Contentful Paint – CSS Wizardry – Internet Efficiency Optimisation

Optimising Largest Contentful Paint – CSS Wizardry – Internet Efficiency Optimisation

Written by on CSS Wizardry.

Desk of Contents
  1. Remedy Every thing Beforehand
  2. Optimise Your LCP Candidate
  3. Keep away from Picture-Based mostly LCPs
  4. Use the Greatest 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-Website
    4. Don’t Construct Your LCP on the Consumer
    5. Don’t Usurp Your Personal LCP
  6. Abstract

Largest Contentful Paint (LCP) is my favorite Core Internet
Important. It’s the simplest to optimise, and it’s the one one of many three that
works the very same within the lab because it does within the area (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 Every thing Beforehand

Let’s begin with the simple stuff. LCP is a milestone timing—it measures…

…the render time of the biggest 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 would 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, and so they’re going to
have a knock-on impact in your LCP. The metrics above don’t matter in and of
themselves, but it surely’s going to assist your LCP if you may get them as little as

is an unimaginable device for getting timings knowledge from CrUX.

An analogy I exploit with non-technical stakeholders goes slightly like this:

It’s worthwhile to get the youngsters to high school for 08:30. That’s all the varsity cares
about—that the youngsters 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. Depart the home with loads of time to spare.
Plan in appropriate buffer time for site visitors points, and so on.

The varsity doesn’t care for those who laid out uniforms the night time earlier than. You might be being
judged in your means to get the youngsters to high school on time; it’s simply frequent sense
to do as a lot as you’ll be able to to make that occur.

Similar together with your LCP. Google doesn’t (at present) care about your TTFB, however a very good
TTFB goes to assist get nearer to a very good LCP.

Optimise your complete chain. Be sure you get the whole lot beforehand as quick as
potential so that you simply’re arrange for fulfillment.

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, make sure that it’s properly optimised—appropriate format, appropriately
sized, sensibly compressed, and so on. Don’t have a 3MB TIFF as your LCP candidate.

Keep away from Picture-Based mostly 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 potential, keep away from
image-based LCP candidates and decide as an alternative for textual LCPs.

The possibilities are, nonetheless, that received’t give you the results you want. Let’s take a look at our different

Use the Greatest Candidate

Okay. Now we’re entering into the enjoyable stuff. Let’s take a look at which LCP candidates
we have now, 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> components
  • <picture> components inside an <svg> factor
  • <video> components (the poster picture is used)
  • A component with a background picture loaded through the
    url() perform (as
    against a CSS
  • Block-level
    components containing textual content nodes or different inline-level textual content components kids.


For the needs of this text, I constructed a collection of lowered demos displaying how
every of the LCP sorts behave. Every of the demos additionally accommodates a reference to
a blocking in-<head> JavaScript file with a view to:

  1. exaggerate the waterfalls, and;
  2. stall the parser to see if or how every LCP sort is impacted by the preload

It’s additionally price noting that every demo may be very stripped again, and doesn’t
essentially characterize real looking circumstances through which many responses could be
in-flight on the identical time. As soon as we run into useful resource rivalry, LCP
candidates’ discovery may go otherwise to what’s exhibited in these lowered
check circumstances. In circumstances like these, we’d look to Precedence
Preload to help. All I’m
eager about proper now’s inherent variations in how browsers deal with sure

The preliminary demos could be discovered at:

The WebPageTest

is offered so that you can look by, although we’ll choose aside particular person
waterfalls later within the article. That every one comes out wanting like this:

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

<img> and poster are an identical in LCP; <picture> in <svg> is the
subsequent quickest
, though there’s a bug within the LCP time that Chrome studies;
background-image-based LCPs are notably the slowest.

A bug in Chrome ≤101 mistakenly studies a textual content node because the LCP
factor. That is fastened 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 most likely our favorite. <img> components, as
lengthy as we don’t mess issues up, are fast to be found by the preload
and as such, could be requested in parallel to previous—even blocking—assets.

<image> and <supply />

It’s price noting that the <image> factor behaves the identical means because the <img
factor. For this reason you might want to write a lot verbose syntax in your
srcset and sizes attributes: the thought is that you simply give the browser sufficient
details about the picture that it could possibly request the related file through the
preload scanner

and never have to attend till structure. (Though, I suppose—technically—there should be
like just a few milliseconds compute overhead figuring out which mixture of
<supply />, srcset, sizes to make use of, however that will likely be mooted fairly shortly
by just about some other shifting half alongside the best way.)

<picture> in <svg>

<picture> components outlined in <svg>s show two very fascinating behaviours.
The primary of which is a straightforward bug through which Chrome misreports the LCP candidate,
seemingly overlooking the <picture> completely. Relying in your context, this
may imply far more beneficial and optimistic LCP scores.

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

As soon as the repair rolls out in M102 (which is Canary on the time of writing, and can
attain Secure on 24 Could, 2022), we
can anticipate correct measurements. This does imply that you could be expertise
degraded LCP scores in your website.

This bug is fastened in Chrome 102.

Due to the present reporting bug, <picture> in <svg> is prone 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 most likely
one thing that you simply wish to verify on sooner moderately than later—your scores are
prone to change.

The bug pertains solely to reported LCP candidate, and doesn’t impression how the
browser really offers with the assets. To that finish, waterfalls in all Chrome
variations look an identical, 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> components outlined in <svg>s look like hidden from the preload
scanner: that’s to say, the href attribute will not be 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
moderately than an oversight. Maybe an optimisation that Chrome may make is to
preload scan embedded SVG in HTML…? However I’m certain that’s far more simply mentioned
than carried out…

<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 /> factor, and is
found early by the preload scanner.

LCP candidate found instantly.

Which means that poster LCPs are inherently fairly quick, in order that’s good

The opposite information is that it appears to be like 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 underneath 2.5s, so both don’t have a <video> LCP in any respect, or ensure 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).

Sources outlined in CSS (mainly something requested through the url()
) are gradual by
default. The commonest candidates listed here are background photographs and net fonts.

The rationale these assets (on this particular case, background photographs) 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’ll be able to learn extra about that on this Twitter thread:

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

Should you at present have a website whose LCP is a background-image, you could be
considering of refactoring or rebuilding that element 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 fashion="background-image: url(lcp.jpg)">
  <img src="lcp.jpg" alt="" width="0" top="0" fashion="show: none !necessary;" />

This little hack permits the preload scanner to choose up the picture, moderately than
ready till the browser is about to render the <div>. This got here in 1.058s
sooner than the naive background-image implementation. You’ll discover that this
waterfall virtually precisely mimics the quickest <img /> possibility:

We may additionally preload this picture, moderately than utilizing an <img /> factor, however
I usually really feel that preload is a little bit of a code odor and must be averted
if potential.


In abstract:

  • text-based LCPs are virtually at all times going to be the quickest;
  • <img /> and poster LCPs are good and quick, discoverable by the preload
  • <video> and not using a poster may need its first body thought-about as an LCP
    candidate in future variations of Chrome;
  • <picture> in <svg> is at present 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 problem by including an invisible <img />.

Alright! Now we all know that are the perfect candidates, is there anything can
do (or keep away from doing) to ensure we aren’t working 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 slightly. 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 that, even when the picture is within the viewport, the browser will nonetheless
late-request it. For this reason you’ll be able to’t safely add loading="lazy" to all of
your photographs and easily hope the browser does (what you assume is) the fitting

In my assessments, lazily loading our picture pushed LCP again to 4.418s: 1.274s slower
than the <img /> variant, and virtually an identical 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, shifting us
to a 3.767s LCP occasion moderately than 3.144s.

Observe 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-Website

The place potential, we must always at all times self-host our static
. This
contains our LCP candidate.

It’s not unusual for website homeowners to make use of third-party picture optimisation providers
reminiscent of Cloudinary to serve each automated and
dynamically optimised photographs: on the fly resizing, format switching,
compression, and so on. Nevertheless, even when considering the efficiency
enhancements of of those providers, the price of heading to a distinct origin
virtually at all times 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 providers for non-critical, non-LCP photographs, but when
you’ll be able to, deliver 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 might assist slightly, it’s nonetheless extremely unlikely
to be sooner than not opening a brand new connection in any respect.

Don’t Construct Your LCP on the Consumer

I see this all too typically, 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 /> factor) will likely be proper
there instantly. Nevertheless, for those who construct your LCP candidate with JS, the method
is far, far more drawn out.

Constructing your LCP candidate in JS may vary from a easy JS-based
picture gallery, proper the best way by to a totally client-rendered web page. The beneath
waterfall reveals 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, ultimately
requests API knowledge in regards to the present product, at entry 50. This response accommodates
details about associated product imagery, which is ultimately put into the
digital DOM as an <img />, lastly initiating a request for the LCP candidate
at entry 53, properly 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 assessments, and what’s necessary to
keep 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 anticipate it to be. Design modals and
cookie banners and so on. to:

  1. load instantly, and;
  2. not really 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 potential for many. Of
the picture based mostly 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