---
layout: post
title: "Optimising Largest Contentful Paint"
date: 2022-03-28 23:02:11
categories: Web Development
main: "https://res.cloudinary.com/csswizardry/image/fetch/f_auto,q_auto/https://csswizardry.com/wp-content/uploads/2022/03/chart-full.png"
meta: "Let’s look at some more technical and non-obvious aspects of optimising Largest Contentful Paint"
faq:
- question: "What is Largest Contentful Paint?"
answer: "Largest Contentful Paint is a Core Web Vitals metric that measures when the largest visible content element in the viewport finishes rendering."
- question: "What usually improves LCP most?"
answer: "The biggest wins usually come from improving server response times, choosing a good LCP candidate, and making sure the browser can discover and prioritise it quickly."
- question: "Should I lazy-load my LCP image?"
answer: "No. Lazy-loading your LCP candidate usually delays it and makes the metric worse."
- question: "Can animations or fades hurt LCP?"
answer: "Yes. Fade-ins and similar effects can delay when the browser considers the content fully rendered, which can worsen LCP."
- question: "Are image-based LCPs always best?"
answer: "Not necessarily. In many cases a text-based candidate is easier to prioritise and can produce a faster, more reliable LCP than a heavy image."
---
[Largest Contentful Paint](https://web.dev/lcp/) (LCP) is my favourite Core Web
Vital. It’s the easiest to optimise, and it’s the only one of the three that
works the exact same in the lab as it does in the field (don’t even get me
started on this…). Yet, surprisingly, it’s the least optimised CWV in CrUX—at
the time of writing, [**only half of origins in the dataset had a Good
LCP**](https://twitter.com/ChromeUXReport/status/1501325517634490376)!
{% include promo.html %}
This genuinely surprises me, because LCP is the simplest metric to improve. So,
in this post, I want to go deep and show you some interesting tricks and
optimisations, as well as some pitfalls and bugs, starting with some very simple
tips.
Let’s go.
## Solve Everything Beforehand
_**Struggling to hit 2.5s?** [Work with me one-to-one and deliver a faster
LCP](/consultancy/)._
Let’s start with the easy stuff. LCP is a milestone timing—it measures…
> …the render time of the largest image or text block visible within the
> viewport, relative to when the page first started loading.
The important thing to note here is that Google doesn’t care how you get to LCP,
as long as you get there fast. There are a lot of other things that could happen
between the start of the page load lifecycle and its LCP. These include (but are
not limited to):
* DNS, TCP, TLS negotiation
* Redirects
* TTFB
* First Paint
* First Contentful Paint
{% include cross-sell.html %}
If any of these are slow, you’re already on the back foot, and they’re going to
have a knock-on effect on your LCP. The metrics above don’t matter in and of
themselves, but it’s going to help your LCP if you can get them as low as
possible.
Treo
is an incredible tool for getting timings data from CrUX.
An analogy I use with non-technical stakeholders goes a little like this:
You need to get the kids to school for 08:30. That’s all the school cares
about—that the kids are there on time. You can do plenty to help make this
happen: prepare their clothes the night before; prepare their lunches the night
before (do the same for yourself). Set appropriate alarms. Have a morning
routine that everyone follows. Leave the house with plenty of time to spare.
Plan in suitable buffer time for traffic issues, etc.
The school doesn’t care if you laid out uniforms the night before. You are being
judged on your ability to get the kids to school on time; it’s just common sense
to do as much as you can to make that happen.
Same with your LCP. Google doesn’t (currently) care about your TTFB, but a good
TTFB is going to help get closer to a good LCP.
Optimise the entire chain. Make sure you get everything beforehand as fast as
possible so that you’re set up for success.
## Optimise Your LCP Candidate
A tip that hopefully doesn’t need me to go into any real detail: if you have an
image-based LCP, make sure it is well optimised—suitable format, appropriately
sized, sensibly compressed, etc. Don’t have a 3MB TIFF as your LCP candidate.
## Avoid Image-Based LCPs
This isn’t going to work for a lot, if not most, sites. But the best way to get
a fast LCP is to ensure that your LCP is text-based. This, in effect, makes your
FCP and LCP synonymous[^1][^2]. That’s it. As simple as that. If possible, avoid
image-based LCP candidates and opt instead for textual LCPs.
The chances are, however, that won’t work for you. Let’s look at our other
options.
## Use the Best Candidate
Okay. Now we’re getting into the fun stuff. Let’s look at which LCP candidates
we have, and whether there are any relative merits to each.
There are several potential candidates for your LCP. Taken straight from
web.dev’s [Largest Contentful Paint (LCP)](https://web.dev/lcp/) page, these
are:
* `` elements
* `` elements inside an `