The defer attribute solves the render-blocking script problem introduced in the HTML Best Practices module's Performance-Friendly HTML lesson, with a precise, predictable execution model worth understanding in full.
1Background Download, Delayed Execution
As introduced in the Performance-Friendly HTML lesson, a plain <script src="..."> forces the HTML parser to pause entirely ā download, execute, then resume parsing ā directly delaying everything below it from rendering. <script defer src="..."> changes this fundamentally: the browser downloads the script in the background while parsing continues uninterrupted, and deliberately delays actually executing it until HTML parsing has fully completed, immediately before the DOMContentLoaded event fires.
This timing guarantee ā execution only after parsing completes ā means a deferred script can always safely assume the complete DOM is available and queryable, without needing to wrap its logic in a DOMContentLoaded listener itself.
2Guaranteed Execution Order Across Multiple Scripts
A critical, distinguishing property: multiple defer scripts are guaranteed by the specification to execute in the exact order they appear in the document ā <script defer src="library.js"> followed by <script defer src="app.js"> guarantees library.js executes first, even if app.js's file happens to finish downloading sooner due to network timing variability.
This makes defer safe for scripts with genuine load-order dependencies ā a library that a subsequent application script relies on ā without requiring any manual coordination logic to enforce that ordering.
3Why defer Should Be The Default Choice
Given its combination of properties ā never blocking HTML parsing, guaranteeing full DOM availability at execution time, and preserving predictable document-order execution across multiple scripts ā defer correctly serves the large majority of real-world application script needs.
Reserve plain blocking <script> tags for the rare case where a script must execute immediately, mid-parse, before any subsequent content exists (uncommon in modern development), and async (covered in the next lesson) specifically for genuinely independent scripts with zero ordering or DOM-dependency requirements, like most third-party analytics tags.
4Step-by-Step Breakdown
Download In The Background, Run When Ready. Recall from the Performance-Friendly HTML lesson: a plain <script> tag blocks HTML parsing entirely until it downloads and executes. defer fixes this specifically ā downloading in the background while parsing continues, then executing at a precise, predictable moment.
defer Downloads In Background, Executes After Parsing. A <script defer src="..."> downloads in parallel with HTML parsing (never blocking it), but its execution is deliberately delayed until parsing completes ā right before the DOMContentLoaded event fires, guaranteeing the full DOM is available to the script.
defer's Core Behavior. When does a deferred script actually execute, relative to HTML parsing?
- āImmediately once the download finishes, interrupting parsing
- āAfter HTML parsing completes entirely, right before DOMContentLoaded
- āBefore HTML parsing even begins
Multiple defer Scripts Execute In Document Order. Unlike async (covered in the next lesson), multiple defer scripts are guaranteed to execute in the exact order they appear in the document, regardless of which one finishes downloading first ā critical when scripts have dependencies on each other.
defer Execution Order. If library.js finishes downloading after app.js (which depends on it), does app.js still risk running before library.js with defer?
- āYes, whichever finishes downloading first always runs first
- āNo, defer guarantees execution in document order regardless of download completion order
- āThe order is unpredictable and browser-dependent
The Correct Default For Most Application Scripts. Given defer never blocks parsing, guarantees DOM availability, and preserves execution order, it's the correct default choice for the large majority of application JavaScript ā reserve plain blocking scripts and async for the specific narrower cases each actually requires.
Choosing defer By Default. Why is defer generally recommended as the default choice for application scripts, rather than a plain blocking <script> tag?
- āThere's no real reason; it's purely stylistic preference
- āIt never blocks parsing, guarantees the DOM is ready, and preserves execution order ā covering most real needs
- āIt makes the actual script file smaller
defer Mastered. You now understand exactly how defer downloads in the background without blocking parsing, guarantees document-order execution across multiple scripts, and why it's the correct default choice for most application JavaScript ā directly extending the Performance-Friendly HTML lesson from earlier in this course.
Defer A Script Without Blocking Parsing. defer downloads in parallel and runs only after the HTML is fully parsed, in document order.
Level Up š
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Non-Blocking Script Loading Directly Supports Faster, More Responsive Initial Rendering For All Users
Users on slower connections or devices, who may disproportionately include those relying on assistive technology with older hardware, benefit particularly from render-blocking delays being eliminated.
SEO Implications
- 1
defer Directly Supports Faster LCP By Eliminating Render-Blocking Script Delays
This directly extends the render-blocking discussion from the Performance-Friendly HTML lesson, connecting a specific, actionable attribute to the Core Web Vitals metric it most directly improves.
Best Practices
Use defer As The Default Attribute For Application Scripts Unless A Specific Reason Requires Otherwise
Its combination of non-blocking loading, guaranteed DOM readiness, and preserved execution order correctly serves the overwhelming majority of real-world script requirements.
Rely On defer's Document-Order Guarantee Instead Of Manual Dependency-Coordination Logic
It eliminates an entire category of race-condition bugs from scripts executing out of their intended dependency order, at zero implementation cost.
Frequent Bugs
A page's LCP score is hurt by render-blocking script tags positioned before critical content.
Add the defer attribute to scripts that don't need to execute before parsing completes, directly addressing the render-blocking delay.
An application script that depends on a library sometimes fails because the library hasn't loaded yet.
Ensure both scripts use defer (not a mix of defer and async, or plain blocking) and are ordered correctly in the document ā defer guarantees document-order execution.
Real-World Examples
A Correctly Ordered Multi-Script Setup
An application with a dependency library and app code, safely ordered using defer.
<script defer src="/vendor/library.js"></script>
<script defer src="/app/main.js"></script>
<!-- main.js can safely assume library.js already executed -->