Critical Rendering Path Optimization
Answer
The Critical Rendering Path (CRP) is the sequence of steps the browser takes to convert HTML, CSS, and JavaScript into rendered pixels. Optimizing it reduces time to first meaningful paint.
Critical Rendering Path
Key Metrics
Optimization Strategies
1. Minimize Critical Resources
<!-- ❌ Render-blocking CSS -->
<link rel="stylesheet" href="all-styles.css" />
<!-- ✅ Split critical and non-critical CSS -->
<style>
/* Inline critical CSS */
.header {
...;
}
.hero {
...;
}
</style>
<link
rel="preload"
href="full-styles.css"
as="style"
onload="this.rel='stylesheet'"
/>
2. Defer Non-Critical JavaScript
<!-- ❌ Parser-blocking -->
<script src="analytics.js"></script>
<!-- ✅ Defer non-critical scripts -->
<script defer src="analytics.js"></script>
<script async src="third-party.js"></script>
3. Preload Critical Resources
<head>
<!-- Preload critical assets -->
<link rel="preload" href="hero-image.webp" as="image" />
<link rel="preload" href="main-font.woff2" as="font" crossorigin />
<link rel="preload" href="critical.css" as="style" />
<!-- Preconnect to required origins -->
<link rel="preconnect" href="https://api.example.com" />
<link rel="dns-prefetch" href="https://cdn.example.com" />
</head>
4. Optimize CSS Delivery
<!-- Critical CSS inline -->
<head>
<style>
/* Above-the-fold styles only */
body {
margin: 0;
font-family: system-ui;
}
.header {
height: 60px;
background: #333;
}
.hero {
min-height: 400px;
}
</style>
</head>
<!-- Load full CSS asynchronously -->
<link
rel="preload"
href="styles.css"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
/>
<noscript><link rel="stylesheet" href="styles.css" /></noscript>
Resource Priority
Measuring CRP
// Performance API
const timing = performance.getEntriesByType("navigation")[0];
console.log("TTFB:", timing.responseStart - timing.requestStart);
console.log("DOM Interactive:", timing.domInteractive);
console.log("DOM Complete:", timing.domComplete);
// Core Web Vitals
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log("LCP:", entry.startTime);
}
}).observe({ entryTypes: ["largest-contentful-paint"] });
Before vs After Optimization
| Metric | Before | After |
|---|---|---|
| Render-blocking resources | 5 | 1 |
| Critical CSS size | 150KB | 15KB |
| First Contentful Paint | 3.2s | 1.1s |
| Time to Interactive | 5.5s | 2.8s |
Tools for Analysis
- Lighthouse: Built into Chrome DevTools
- WebPageTest: Detailed waterfall analysis
- Chrome DevTools Coverage: Find unused CSS/JS
- Critical: Extract critical CSS automatically
Key Points
- Inline critical CSS, defer the rest
- Use
deferandasyncfor JavaScript - Preload critical assets
- Minimize render-blocking resources
- Measure with Real User Monitoring (RUM)