HTML Tutorial 0/139 lessons ~6 min read Lesson 98

    Largest Contentful Paint (LCP)

    largest contentful paint (lcp) largest contentful paint captures when main content becomes visible. chrome team largest contentful paint (lcp) marks

    Course progress0%
    Focus
    18 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Largest Contentful Paint (LCP) marks when the largest content element in the viewport paints — typically hero image, heading block, or video poster. The Chrome team defines LCP on web.dev as a primary loading metric in Core Web Vitals; CrUX reports p75 LCP per origin and URL.

    LCP is not DOMContentLoaded or load event — it is paint timing of a specific element, making HTML choices (preload, fetchpriority, dimensions) decisive.

    Business problem

    Business pressure: E-commerce hero image served as unoptimized PNG from third-party CMS — LCP 6.2s mobile CrUX. Category pages lost "Good" status; paid search quality score indirectly affected. Fix was HTML preload + WebP + width/height — not CDN upgrade alone.

    • Conversion: web.dev LCP case studies show measurable conversion lift when LCP drops below 2.5s.
    • Compliance: Delayed text paint affects users relying on quick content access — cognitive load increases.
    • SEO: LCP is most visible CrUX metric in Search Console — Poor LCP flags URLs directly.

    Why this feature exists

    Platform motivation: load event fires late (all resources); FCP fires early (any paint). LCP correlates with "main content visible" — what users actually wait for on landing pages.

    • History: Largest Contentful Paint standardized via WICG LCP spec; adopted into CWV 2020.
    • Alternative rejected: First Meaningful Paint deprecated — heuristic, inconsistent across engines.
    • Modern role: LCP element attribution in PerformancePanel guides surgical fixes.

    Browser internals

    Inside the engine: PerformanceObserver watches largest-contentful-paint entries. Candidates: block-level elements containing text nodes, img, svg image, video poster, background-image on block elements. Size = visible area in viewport. New larger paint replaces candidate until interaction or navigation.

    • Text LCP: Often h1 — web font load can delay text paint (FOIT/FOUT).
    • Image LCP: Paint when image bytes decoded and drawn — network + render pipeline.
    • Soft nav: SPA route changes can emit new LCP — soft navigation API experimental.
    • Excluded: overflow hidden content, svg filters, opacity 0 elements.
    text
    LCP timeline (typical image hero)
    Navigation start
    → TTFB (HTML)
    → DOM discovers <img src hero.webp>
    → (preload?) resource fetch starts early
    → CSSOM ready → layout assigns box
    → Image decode + paint
    → LCP entry recorded

    Rendering workflow

    Rendering path: LCP requires element in DOM, styled, laid out, and painted. CRP delays push LCP. Client-only LCP element waits for JS hydration — common SPA failure mode in CrUX.

    • Critical path: Discover → load → paint for LCP resource — minimize each segment per web.dev LCP guide.
    • Layout: Must complete before paint records LCP geometry.
    • Paint: LCP timestamp is render timestamp, not resource download complete.

    Feature deep dive

    LCP optimization checklist from web.dev: reduce TTFB; remove render-blocking resources; compress and prioritize LCP image; inline critical CSS; use CDN; avoid client-side render for LCP element if possible.

    • fetchpriority="high": On LCP img — Chrome priority boost.
    • preload: <link rel=preload as=image href=...> in head before late body discovery.
    • Responsive: srcset/sizes so mobile does not download desktop hero bytes.
    • SSR: LCP element in first HTML chunk — not after JS bundle.
    html
    <link rel="preload" as="image" href="/hero.avif"
    imagesrcset="/hero-640.avif 640w, /hero-1280.avif 1280w"
    imagesizes="100vw" fetchpriority="high">
    <img src="/hero.avif" width="1280" height="640"
    alt="Product hero" fetchpriority="high">

    Accessibility analysis

    A11y architecture: If LCP is decorative image while meaningful h1 paints late, users with images off see delayed meaningful content. Prefer text LCP with proper heading in HTML; alt text on image LCP for screen readers.

    • Screen readers: LCP image needs descriptive alt — not performance-only concern.
    • Keyboard: N/A to LCP timing directly.
    • WCAG: Text contrast must be ready when LCP text paints — avoid invisible text during font load.

    SEO impact

    SEO architecture: Googlebot WRS measures LCP for rendering evaluation. Slow LCP URLs appear in Search Console CWV report. Image LCP without alt hurts image search and accessibility indirectly.

    • Crawl: Render queue timeout may index before LCP completes — still prefer fast LCP HTML.
    • Rich results: Product image LCP should match primary product image in schema.
    • Core Web Vitals: LCP is one of three ranking-related experience signals.

    Security considerations

    Security boundary: Preload only trusted origins — preload attacker URL wastes bandwidth. CSP img-src restricts LCP resource source.

    • XSS: If attacker controls img src, LCP loads malicious resource — CSP mitigates.
    • CSP: img-src and connect-src affect LCP resource loading.
    • Clickjacking: Unrelated to LCP measurement.

    Performance impact

    Performance: LCP subparts (experimental): TTFB, resource load delay, resource load time, element render delay — Chrome DevTools and web.dev explain attribution for each segment.

    • LCP: The metric — optimize all CRP and resource priorities toward it.
    • INP: Heavy JS during LCP window can delay paint — defer non-critical script.
    • CLS: Sized LCP element prevents shift when image arrives — dual win.

    Real production example

    Production pattern: Smashing Magazine documented AVIF hero with preload and critical CSS — LCP dropped from 4.1s to 1.8s mobile lab; field CrUX followed over 28 days. Pattern matches web.dev LCP optimization guide from Chrome DevRel.

    • Pattern: AVIF with JPEG fallback; preload AVIF; width/height attributes.
    • Monitoring: RUM LCP element selector logged — verify hero is candidate.
    • Fix: Moved hero img before JS-heavy carousel in DOM — discovery 400ms earlier.

    Enterprise usage

    Enterprise: CMS enforces hero image slot with required dimensions, format (AVIF/WebP), and automatic preload link generation in head template.

    • Design system: Hero component emits preload + img with fetchpriority high.
    • CMS: Crop presets match srcset breakpoints — no 2MB mobile download.
    • CI gates: Lighthouse LCP audit on homepage template every deploy.

    Common production failures

    What breaks in prod: Lazy-loading applied to above-fold hero via blanket loading=lazy — LCP delayed until scroll heuristic, CrUX LCP +2s. web.dev explicitly warns against lazy LCP image.

    • Incident: CSS background-image hero — slower LCP than img tag; switch fixed LCP.
    • SEO regression: Client-rendered h1 — LCP waited for React hydration 3.5s.
    • Perf regression: Removed preload "to reduce warnings" — LCP resource load delay spiked.

    Architecture review questions

    • What element is LCP on our top 10 URLs — img, text, or video poster?
    • Is LCP image preloaded with fetchpriority=high and not lazy-loaded?
    • What are LCP subparts in DevTools — which segment dominates?
    • Does SSR HTML include LCP element before main JS bundle?
    • Are web fonts blocking LCP text paint — font-display strategy?
    • CrUX LCP p75 vs lab delta — cache, geography, or device explanation?

    Hands-on project

    Project: Identify LCP element on your homepage via DevTools Performance (LCP marker). Implement preload + dimensions + modern format. Measure before/after lab and document expected CrUX timeline.

    • Deliverable: Lighthouse LCP + screenshot of LCP element in Elements panel.
    • Verify: web.dev optimize LCP checklist; PageSpeed Insights field data.
    • Stretch: Add LCP attribution logging with web-vitals.js.

    Interview questions

    What elements can be LCP candidates?(Intermediate)

    img, svg image, video poster, block with text nodes, block with background-image. Largest visible area in viewport wins until user input. Defined in LCP spec and web.dev docs.

    Follow-up: Can LCP change after initial paint?

    How do you optimize LCP for an image hero?(Advanced)

    SSR img in HTML, preload link, fetchpriority high, responsive srcset, AVIF/WebP, width/height for CLS, remove render-blocking CSS/JS from CRP, improve TTFB. Trace subparts in DevTools.

    Follow-up: Why not lazy-load hero?

    LCP improved in lab but not CrUX — why?(Advanced)

    28-day rolling window; geographic/device mix; real cache cold starts; A/B tests; third-party variance. CrUX needs sustained fix. Check RUM segmented by country and device class.

    Follow-up: Minimum traffic for CrUX URL-level data?

    Try it yourself

    Edit the HTML, CSS, or JS panels — the preview updates as you type.

    Try it yourself

    Preview

    Summary

    Largest Contentful Paint captures when main content becomes visible. Chrome team web.dev LCP guide defines HTML-level optimizations — preload, priority, formats, and CRP — validated against CrUX p75 in production.

    Ready to mark this lesson complete?Track your journey across the entire course.