Last updated
Render Blocking Resources Examples
The Render Blocking Resources tool identifies CSS and JavaScript that blocks the browser from rendering page content. Below are examples of common blocking issues and their fixes.
What Render Blocking Looks Like
A page with multiple blocking resources in the head:
<!-- BEFORE: All resources block rendering -->
<head>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/app.css">
<link rel="stylesheet" href="/css/print.css">
<script src="/js/jquery.min.js"></script>
<script src="/js/analytics.js"></script>
<script src="/js/app.js"></script>
</head>
The browser stops rendering until all 6 files are downloaded and processed. On a slow connection this can add 3-5 seconds before any content appears.
Fix: Defer Non-Critical JavaScript
Add the defer attribute to scripts that don't need to run before rendering:
<!-- AFTER: Scripts deferred, run after HTML parsing -->
<head>
<link rel="stylesheet" href="/css/app.css">
<script src="/js/jquery.min.js" defer></script>
<script src="/js/analytics.js" defer></script>
<script src="/js/app.js" defer></script>
</head>
Deferred scripts execute after HTML parsing completes but before DOMContentLoaded. They don't block rendering.
Fix: Async for Independent Scripts
Use async for scripts that don't depend on other scripts or the DOM:
<!-- Analytics doesn't need the DOM — use async -->
<script src="/js/analytics.js" async></script>
<!-- App script depends on jQuery — use defer to preserve order -->
<script src="/js/jquery.min.js" defer></script>
<script src="/js/app.js" defer></script>
async scripts execute as soon as they download, in any order. defer scripts execute in order after parsing. Use async only for truly independent scripts.
Fix: Non-Critical CSS with Media Queries
Load print styles without blocking rendering:
<!-- BEFORE: Print CSS blocks all rendering -->
<link rel="stylesheet" href="/css/print.css">
<!-- AFTER: Print CSS only blocks when printing -->
<link rel="stylesheet" href="/css/print.css" media="print">
Adding media="print" tells the browser this stylesheet is only needed for printing. It's still downloaded but doesn't block the initial render.
Fix: Critical CSS Inlining
Inline the CSS needed for above-the-fold content, load the rest asynchronously:
<head>
<!-- Critical CSS inlined — no network request needed -->
<style>
body { margin: 0; font-family: sans-serif; }
header { background: #1a1a2e; color: white; padding: 1rem; }
.hero { min-height: 60vh; display: flex; align-items: center; }
h1 { font-size: 2.5rem; }
</style>
<!-- Full CSS loaded asynchronously after render -->
<link rel="preload" href="/css/app.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/app.css"></noscript>
</head>
Critical CSS inlining eliminates the render-blocking CSS request entirely for the initial view. First Contentful Paint (FCP) improves significantly.
Fix: Third-Party Script Loading
Load third-party analytics and chat widgets without blocking rendering:
<!-- BEFORE: Third-party scripts block rendering -->
<script src="https://www.googletagmanager.com/gtag/js?id=GA_ID"></script>
<script src="https://widget.intercom.io/widget/APP_ID"></script>
<!-- AFTER: Load after page is interactive -->
<script>
window.addEventListener('load', function() {
// Load analytics after page load
var script = document.createElement('script');
script.src = 'https://www.googletagmanager.com/gtag/js?id=GA_ID';
script.async = true;
document.head.appendChild(script);
});
</script>
<!-- Or simply use async -->
<script async src="https://www.googletagmanager.com/gtag/js?id=GA_ID"></script>
Fix: Web Font Loading
Prevent fonts from blocking rendering with font-display:
<!-- BEFORE: Font blocks rendering until loaded -->
<style>
@font-face {
font-family: 'MyFont';
src: url('/fonts/myfont.woff2') format('woff2');
}
</style>
<!-- AFTER: Show fallback font immediately, swap when loaded -->
<style>
@font-face {
font-family: 'MyFont';
src: url('/fonts/myfont.woff2') format('woff2');
font-display: swap;
}
</style>
<!-- Also preload the font file -->
<link rel="preload" href="/fonts/myfont.woff2" as="font" type="font/woff2" crossorigin>
Performance Impact Estimates
Expected improvements after applying optimizations:
Metric Before After Improvement
First Contentful Paint 3.2s 0.8s -75%
Largest Contentful Paint 4.1s 1.6s -61%
Time to Interactive 5.8s 2.1s -64%
Total Blocking Time 1200ms 80ms -93%
Lighthouse Score 42 91 +49 points
Waterfall Chart — Before vs After
Resource loading sequence comparison:
BEFORE (blocking):
0ms ─── HTML parsing starts
50ms ─── CSS 1 download starts (BLOCKS)
300ms─── CSS 1 done, CSS 2 starts (BLOCKS)
600ms─── CSS 2 done, JS 1 starts (BLOCKS)
900ms─── JS 1 done, JS 2 starts (BLOCKS)
1200ms── JS 2 done → FIRST RENDER
AFTER (non-blocking):
0ms ─── HTML parsing starts
50ms ─── Critical CSS applied (inline)
80ms ─── FIRST RENDER ← 15x faster
100ms─── Deferred JS downloads (background)
400ms─── Full CSS loads (background)
500ms─── Deferred JS executes
- Identify all render-blocking CSS and JavaScript files
- Add defer or async to non-critical scripts
- Use media queries to prevent non-critical CSS from blocking
- Inline critical CSS for above-the-fold content
- Load third-party scripts asynchronously or after page load
- Use font-display: swap to prevent font render blocking
- View performance impact estimates for each optimization
- Waterfall chart shows the loading sequence before and after