The defer attribute is a boolean attribute on <script src="..."> elements. It tells the browser to download the script in parallel with HTML parsing, then execute it after the document has been fully parsed—without blocking page rendering. Deferred scripts run in document order, which makes defer ideal for app logic that depends on the DOM.
01
Non-Blocking
Parse HTML first.
02
External src
Requires src URL.
03
Boolean
Presence = defer.
04
Order Kept
Scripts run in sequence.
05
vs async
Compare loading.
06
JavaScript
script.defer = true.
Fundamentals
Purpose of defer
Without defer or async, a classic script in the <head> can block HTML parsing while it downloads and runs. The defer attribute improves page load performance by letting parsing continue while the script file downloads in the background. Execution is postponed until the HTML document is fully parsed.
Because deferred scripts run in the order they appear in the document, you can safely load a library first and an app script second. Deferred scripts typically run before the DOMContentLoaded event fires.
💡
External scripts only
defer applies to <script src="..."> only. It has no effect on inline scripts without a src attribute.
Foundation
📝 Syntax
Add defer to an external <script> element:
defer.html
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><scriptdefersrc="app.js"></script></head><body><!-- HTML content --></body></html>
Syntax Rules
Boolean attribute: write defer alone or as defer="".
Requires a src attribute pointing to an external JavaScript file.
Only valid on <script> elements.
Do not combine defer and async on the same tag (async wins).
Reference
💎 Values
The defer attribute is a boolean attribute. It has no meaningful string values:
Attribute present — Script downloads in parallel and runs after HTML parsing, in document order.
Attribute absent — Default parser-blocking behavior (unless async is used).
defer-boolean.html
<!-- Deferred external script --><scriptdefersrc="analytics.js"></script><!-- Equivalent boolean form --><scriptdefer=""src="analytics.js"></script>
Cheat Sheet
⚡ Quick Reference
Item
Details
Notes
Element
<script src="...">
External scripts only
Type
Boolean attribute
Presence = deferred
Download
Parallel with parsing
Non-blocking fetch
Execution
After HTML parsed
Before DOMContentLoaded
Order
Document order preserved
Unlike async
JS property
scriptElement.defer
true or false
Scope
Applicable Elements
Element
Supported?
Notes
<script src="...">
Yes
Primary and standard use
<script> inline (no src)
No effect
defer is ignored without src
<link>, <img>
No
Not valid on these elements
Module scripts
Deferred by default
type="module" behaves like defer
Compare
defer vs async
Behavior
defer
async
Download
Parallel with parsing
Parallel with parsing
When it runs
After HTML is fully parsed
As soon as download completes
Execution order
Preserved (document order)
Not guaranteed
Best for
App scripts that need the DOM
Independent widgets, analytics
Both on same tag
Avoid — async takes precedence; defer is ignored
defer-async.html
<!-- Independent analytics: async --><scriptasyncsrc="analytics.js"></script><!-- App logic that needs DOM and order: defer --><scriptdefersrc="utils.js"></script><scriptdefersrc="app.js"></script>
Hands-On
Examples Gallery
Basic deferred scripts, dynamic JavaScript loading, and preserved execution order.
Example — Deferred External Script
A script in the <head> with defer does not block HTML parsing:
Even if app.js finishes downloading first, the browser waits until parsing completes and runs utils.js before app.js.
A11y
♿ Accessibility & UX
Faster first paint — Deferring non-critical scripts helps content appear sooner, which benefits all users including those on slow connections.
Do not defer critical UI — Scripts that inject essential accessibility features (skip links, focus management) may need to run earlier.
Avoid layout shifts — Deferred scripts that modify the DOM after load can cause unexpected jumps; reserve space or use stable markup.
Test without JavaScript — Core content should remain usable if scripts fail to load.
🧠 How defer Works
1
Browser finds defer script
Starts downloading the file in parallel.
Fetch
2
HTML parsing continues
Page content renders without waiting for the script.
Parse
3
Document fully parsed
Deferred scripts run in document order.
Execute
=
⚡
Fast page, safe DOM access
Scripts run after HTML is ready without blocking rendering.
Compatibility
Browser Support
The defer attribute is supported in all modern browsers for external scripts. It has been widely available since IE 10.
✓ HTML5 · Fully supported
Deferred scripts everywhere
Chrome, Firefox, Safari, and Edge all support defer on external <script> tags.
99%Browser support
Google ChromeFully supported
Full support
Mozilla FirefoxFully supported
Full support
Apple SafariFully supported
Full support
Microsoft EdgeFully supported
Full support
Internet ExplorerIE 10+ supported
Full support
defer attribute99% supported
Bottom line: Use defer confidently on external scripts in modern projects.
Pro Tips
💡 Best Practices
✅ Do
Use defer for app scripts that need the full DOM
Keep dependent scripts in document order with defer
Place deferred scripts in the head for early download
Use async for independent third-party widgets
Test script timing with and without defer
❌ Don’t
Add defer to inline scripts without src
Combine async and defer on the same script tag
Defer scripts that must run before HTML renders
Assume defer works on dynamically inserted inline code
Load interdependent scripts with async
Wrap Up
Conclusion
The defer attribute is a valuable tool for optimizing web page loading performance. It lets external scripts download in parallel while HTML parsing continues, then executes them in order after the document is ready.
Use defer for application logic that depends on the DOM. Use async for standalone scripts that do not depend on order or DOM readiness. Never combine both on the same tag.