WebPerf: Core Web Vitals
JavaScript snippets for measuring web performance in Chrome DevTools. Execute with
mcp__chrome-devtools__evaluate_script
, capture output with
mcp__chrome-devtools__get_console_message
.
Available Snippets
| Snippet | Description | File |
|---|
| Cumulative Layout Shift (CLS) | Quick check for Cumulative Layout Shift, a Core Web Vital that measures visual stability | scripts/CLS.js |
| Interaction to Next Paint (INP) | Tracks Interaction to Next Paint, a Core Web Vital that measures responsiveness | scripts/INP.js |
| LCP Image Entropy | Checks if images qualify as LCP candidates based on their entropy (bits per pixel) | scripts/LCP-Image-Entropy.js |
| LCP Sub-Parts | Breaks down Largest Contentful Paint into its four phases to identify optimization opportunities | scripts/LCP-Sub-Parts.js |
| LCP Trail | Tracks every LCP candidate element during page load and highlights each one with a distinct pastel-c | scripts/LCP-Trail.js |
| LCP Video Candidate | Detects whether the LCP element is a <video> and audits the poster image configuration — the most co | scripts/LCP-Video-Candidate.js |
| Largest Contentful Paint (LCP) | Quick check for Largest Contentful Paint, a Core Web Vital that measures loading performance | scripts/LCP.js |
Execution with Chrome DevTools MCP
1. mcp__chrome-devtools__navigate_page → navigate to target URL
2. mcp__chrome-devtools__evaluate_script → run snippet code (read from scripts/ file)
3. mcp__chrome-devtools__get_console_message → capture console output
4. Interpret results using thresholds below, provide recommendations
Common Workflows
Complete Core Web Vitals Audit
When the user asks for a comprehensive Core Web Vitals analysis or "audit CWV":
- LCP.js - Measure Largest Contentful Paint
- CLS.js - Measure Cumulative Layout Shift
- INP.js - Measure Interaction to Next Paint
- LCP-Sub-Parts.js - Break down LCP timing phases
- LCP-Trail.js - Track LCP candidate evolution
LCP Deep Dive
When LCP is slow or the user asks "debug LCP" or "why is LCP slow":
- LCP.js - Establish baseline LCP value
- LCP-Sub-Parts.js - Break down into TTFB, resource load, render delay
- LCP-Trail.js - Identify all LCP candidates and changes
- LCP-Image-Entropy.js - Check if LCP image has visual complexity issues
- LCP-Video-Candidate.js - Detect if LCP is a video (poster or video element)
CLS Investigation
When layout shifts are detected or the user asks "debug CLS" or "layout shift issues":
- CLS.js - Measure overall CLS score
- Layout-Shift-Loading-and-Interaction.js (from Interaction skill) - Separate loading vs interaction shifts
- Cross-reference with webperf-loading skill:
- Find-Above-The-Fold-Lazy-Loaded-Images.js (lazy images causing shifts)
- Fonts-Preloaded-Loaded-and-used-above-the-fold.js (font swap causing shifts)
INP Debugging
When interactions feel slow or the user asks "debug INP" or "slow interactions":
- INP.js - Measure overall INP value
- Interactions.js (from Interaction skill) - List all interactions with timing
- Input-Latency-Breakdown.js (from Interaction skill) - Break down input delay, processing, presentation
- Long-Animation-Frames.js (from Interaction skill) - Identify blocking animation frames
- Long-Animation-Frames-Script-Attribution.js (from Interaction skill) - Find scripts causing delays
Video as LCP Investigation
When LCP is a video element (detected by LCP-Video-Candidate.js):
- LCP-Video-Candidate.js - Identify video as LCP candidate
- Video-Element-Audit.js (from Media skill) - Audit video loading strategy
- LCP-Sub-Parts.js - Analyze video loading phases
- Cross-reference with webperf-loading skill:
- Resource-Hints-Validation.js (check for video preload)
- Priority-Hints-Audit.js (check for fetchpriority on video)
Image as LCP Investigation
When LCP is an image (most common case):
- LCP.js - Measure LCP timing
- LCP-Sub-Parts.js - Break down timing phases
- LCP-Image-Entropy.js - Analyze image complexity
- Cross-reference with webperf-media skill:
- Image-Element-Audit.js (check format, dimensions, lazy loading)
- Cross-reference with webperf-loading skill:
- Find-Above-The-Fold-Lazy-Loaded-Images.js (check if incorrectly lazy)
- Priority-Hints-Audit.js (check for fetchpriority="high")
- Resource-Hints-Validation.js (check for preload)
Decision Tree
Use this decision tree to automatically run follow-up snippets based on results:
After LCP.js
- If LCP > 2.5s → Run LCP-Sub-Parts.js to diagnose which phase is slow
- If LCP > 4.0s (poor) → Run full LCP deep dive workflow (5 snippets)
- If LCP candidate is an image → Run LCP-Image-Entropy.js and webperf-media:Image-Element-Audit.js
- If LCP candidate is a video → Run LCP-Video-Candidate.js and webperf-media:Video-Element-Audit.js
- Always run → LCP-Trail.js to understand candidate evolution
After LCP-Sub-Parts.js
- If TTFB phase > 600ms → Switch to webperf-loading skill and run TTFB-Sub-Parts.js
- If Resource Load Time > 1500ms → Run:
- webperf-loading:Resource-Hints-Validation.js (check for preload/preconnect)
- webperf-loading:Priority-Hints-Audit.js (check fetchpriority)
- webperf-loading:Find-render-blocking-resources.js (competing resources)
- If Render Delay > 200ms → Run:
- webperf-loading:Find-render-blocking-resources.js (blocking CSS/JS)
- webperf-loading:Script-Loading.js (parser-blocking scripts)
- webperf-interaction:Long-Animation-Frames.js (main thread blocking)
After LCP-Trail.js
- If many LCP candidate changes (>3) → This causes visual instability, investigate:
- webperf-loading:Find-Above-The-Fold-Lazy-Loaded-Images.js (late-loading images)
- webperf-loading:Fonts-Preloaded-Loaded-and-used-above-the-fold.js (font swaps)
- CLS.js (layout shifts contributing to LCP changes)
- If final LCP candidate appears late → Run webperf-loading:Resource-Hints-Validation.js
- If early candidate was replaced → Understand why initial content was pushed down (likely CLS issue)
After LCP-Image-Entropy.js
- If entropy is very high → Image is visually complex, recommend:
- Modern formats (WebP, AVIF)
- Appropriate compression
- Potentially a placeholder strategy
- If entropy is low → Image may be over-optimized or placeholder-like
- If large file size detected → Run webperf-media:Image-Element-Audit.js for format/sizing analysis
After LCP-Video-Candidate.js
- If video is LCP → Run:
- webperf-media:Video-Element-Audit.js (check poster, preload, formats)
- webperf-loading:Priority-Hints-Audit.js (check fetchpriority on poster)
- LCP-Sub-Parts.js (analyze video loading phases)
- If poster image is LCP → Treat as image LCP (run image workflows)
After CLS.js
- If CLS > 0.1 → Run webperf-interaction:Layout-Shift-Loading-and-Interaction.js to separate causes
- If CLS > 0.25 (poor) → Run comprehensive shift investigation:
- webperf-loading:Find-Above-The-Fold-Lazy-Loaded-Images.js (images without dimensions)
- webperf-loading:Fonts-Preloaded-Loaded-and-used-above-the-fold.js (font loading strategy)
- webperf-loading:Critical-CSS-Detection.js (late-loading styles)
- webperf-media:Image-Element-Audit.js (missing width/height)
- If CLS = 0 → Confirm with multiple page loads (might be timing-dependent)
After INP.js
- If INP > 200ms → Run webperf-interaction:Interactions.js to identify slow interactions
- If INP > 500ms (poor) → Run full INP debugging workflow:
- webperf-interaction:Interactions.js (list all interactions)
- webperf-interaction:Input-Latency-Breakdown.js (phase breakdown)
- webperf-interaction:Long-Animation-Frames.js (blocking frames)
- webperf-interaction:Long-Animation-Frames-Script-Attribution.js (culprit scripts)
- If specific interaction type is slow (e.g., keyboard) → Focus analysis on that interaction type
Cross-Skill Triggers
These triggers recommend using snippets from other skills:
From LCP to Loading Skill
-
If LCP > 2.5s and TTFB phase is dominant → Use webperf-loading skill:
- TTFB.js, TTFB-Sub-Parts.js, Service-Worker-Analysis.js
-
If LCP image is lazy-loaded → Use webperf-loading skill:
- Find-Above-The-Fold-Lazy-Loaded-Images.js
-
If LCP has no fetchpriority → Use webperf-loading skill:
From CLS to Loading Skill
-
If CLS caused by fonts → Use webperf-loading skill:
- Fonts-Preloaded-Loaded-and-used-above-the-fold.js
- Resource-Hints-Validation.js (for font preload)
-
If CLS caused by images → Use webperf-media skill:
- Image-Element-Audit.js (check for width/height attributes)
From INP to Interaction Skill
- If INP > 200ms → Use webperf-interaction skill for full debugging:
- Interactions.js, Input-Latency-Breakdown.js
- Long-Animation-Frames.js, Long-Animation-Frames-Script-Attribution.js
- LongTask.js (if pre-interaction blocking suspected)
From LCP/INP to Interaction Skill
- If render delay or interaction delay is high → Use webperf-interaction skill:
- Long-Animation-Frames.js (main thread blocking)
- LongTask.js (long tasks delaying rendering)
Multi-Metric Correlation
When multiple CWV metrics are poor, prioritize investigation:
-
If LCP > 2.5s AND CLS > 0.1 → Likely shared root cause:
- Check for late-loading content pushing LCP element
- Run LCP-Trail.js to see LCP candidate changes
- Run Layout-Shift-Loading-and-Interaction.js to correlate timing
-
If LCP > 2.5s AND INP > 200ms → Main thread congestion:
- Run Long-Animation-Frames.js
- Run webperf-loading:Script-Loading.js
- Run webperf-loading:JS-Execution-Time-Breakdown.js
-
If CLS > 0.1 AND INP > 200ms → Layout thrashing or interaction-triggered shifts:
- Run Layout-Shift-Loading-and-Interaction.js
- Run Interactions.js
- Check if shifts occur during/after interactions
Cumulative Layout Shift (CLS)
Quick check for Cumulative Layout Shift, a Core Web Vital that measures visual stability. CLS tracks how much the page layout shifts unexpectedly during its lifetime, providing a single score that represents the cumulative impact of all unexpected layout shifts.
Thresholds:
| Rating | Score | Meaning |
|---|
| 🟢 Good | ≤ 0.1 | Stable, minimal shifting |
| 🟡 Needs Improvement | ≤ 0.25 | Noticeable shifting |
| 🔴 Poor | > 0.25 | Significant layout instability |
Interaction to Next Paint (INP)
Tracks Interaction to Next Paint, a Core Web Vital that measures responsiveness. INP evaluates how quickly a page responds to user interactions throughout the entire page visit, replacing First Input Delay (FID) as a Core Web Vital in March 2024.
Thresholds:
| Rating | Time | Meaning |
|---|
| 🟢 Good | ≤ 200ms | Responsive, feels instant |
| 🟡 Needs Improvement | ≤ 500ms | Noticeable delay |
| 🔴 Poor | > 500ms | Slow, frustrating experience |
LCP Image Entropy
Checks if images qualify as LCP candidates based on their entropy (bits per pixel). Since Chrome 112, low-entropy images are ignored for LCP measurement.
Script: scripts/LCP-Image-Entropy.js
Thresholds:
| BPP | Entropy | LCP Eligible | Example |
|---|
| < 0.05 | 🔴 Low | ❌ No | Solid colors, simple gradients, placeholders |
| ≥ 0.05 | 🟢 Normal | ✅ Yes | Photos, complex graphics |
LCP Sub-Parts
Breaks down Largest Contentful Paint into its four phases to identify optimization opportunities. Understanding which phase is slowest helps you focus your optimization efforts where they'll have the most impact. Based on the Web Vitals Chrome Extension.
LCP Trail
Tracks every LCP candidate element during page load and highlights each one with a distinct pastel-colored dashed outline — so you can see the full trail from first candidate to final LCP.
LCP Video Candidate
Detects whether the LCP element is a <video> and audits the poster image configuration — the most common source of avoidable LCP delay when video is the hero element.
Script: scripts/LCP-Video-Candidate.js
Largest Contentful Paint (LCP)
Quick check for Largest Contentful Paint, a Core Web Vital that measures loading performance. LCP marks when the largest content element becomes visible in the viewport.
Thresholds:
| Rating | Time | Meaning |
|---|
| 🟢 Good | ≤ 2.5s | Fast, content appears quickly |
| 🟡 Needs Improvement | ≤ 4s | Moderate delay |
| 🔴 Poor | > 4s | Slow, users may abandon |