Blog #20: The Mystery of LCP – Why do 'fast' websites still get rated low?
LCP isn't just about image compression. Discover the 4 stages of the 'Big Picture' and how to optimize the entire resource supply chain.
"Why do I see content appear almost instantly, yet Lighthouse still scolds me with a bright red LCP score of up to 4 seconds?"
This question is often the beginning of a journey to discover how browsers actually measure "The Feeling of Speed." LCP (Largest Contentful Paint) is not just a number; it's the result of a Resource Supply Chain across from the server all the way to the user's GPU. To decode the mystery of LCP, we must look at it from the perspective of the data flow architecture, not just a Hero image.
1. Overall Architecture: 4 Stages of a "Big Picture"
LCP is composed of 4 consecutive timestamps in the system:
- TTFB (Time to First Byte): Speed at which the server responds with the first HTML bytes.
- Resource Load Delay: The time between having HTML and the browser "realizing" it needs to load the LCP image.
- Resource Load Duration: The actual time to load that image over the network.
- Element Render Delay: The time from finishing the image download to it actually being drawn on the screen.
The problem for most of us is focusing only on stage 3 (image compression), while stages 2 and 4 are the "silent killers."
2. Analysis of Data Flow & Discovery Flow
Look at how the system discovers resources:
- Discovery Flow: HTML Parsed → Scanner detects Image URL? (If the URL is inside JS, the Scanner is blind to it) → Request sent.
- The Issue: If you use libraries like
framer-motionto animate the Hero image, or have a Hero image in a component that must wait for an API fetch to appear, you've accidentally created a massive Render Delay.
/* System Error: LCP image hidden in JS */
const Hero = () => {
const { data } = useSWR('/api/banner'); // LCP must wait for API!
if (!data) return null;
return <img src={data.url} />;
};
3. Quick Fix vs. Architectural Refactoring
Quick Fix: Compress images into extremely small AVIF format. This helps stage 3 be a bit faster but doesn't save the 2 seconds wasted in stage 2 when the browser has to wait for JS to load before it can see the image URL.
Architectural Refactoring (Architectural Fix):
- Early Discovery: Place the Hero image in plain HTML as a traditional
<img>tag or use<link rel="preload">. Let the browser see the image as soon as it receives the first HTML bytes. - Zero In-lining: Avoid in-lining Base64 images into CSS/JS. It inflates the code files and slows down the entire system's parsing process.
- Prioritization: Use
fetchpriority="high"to tell the network system: "Set everything aside, this is the most important thing!".
4. Technical Debt and Self-Reflection
Trying to achieve a high LCP score without understanding those 4 stages is a technical debt of mindset. You'll fall into changing network infrastructure (upgrading servers, using premium CDNs) while the actual error lies in how you structure your components at the Frontend. This leads to financial waste with underwhelming results.
I wonder: "Are we sacrificing too much speed just for a few flashy fade-in effects?". Sometimes, an image appearing "pop" instantly is ten thousand times better than a smooth effect that makes users wait under a blank screen. Stability and clarity are the peak of UX.
Lesson Learned
LCP is a test of System Honesty. It exposes the delays we deliberately hide behind complex components. Treat the most important content with the highest priority right from the first HTML layer.
Notes on the journey of an important pixel.
Series • Part 20 of 50