You added defer to your scripts to avoid blocking rendering. But scripts still block, or they run in the wrong order. This is common: defer has specific behavior that is easy to misunderstand. This guide explains why JavaScript defer is not working and how to fix it.
What defer does
The defer attribute tells the browser to download the script in parallel and execute it after the HTML is parsed, before DOMContentLoaded.
Example:
<script src="app.js" defer></script>
Defer is useful for scripts that need the DOM but are not critical for initial rendering.
But defer has rules:
— it works only for external scripts;
— it does not work for inline scripts;
— deferred scripts execute in order;
— defer is ignored for module scripts in some contexts.
Why defer matters
Without defer, scripts block HTML parsing. This delays rendering and hurts Core Web Vitals.
With defer:
— HTML parses without blocking;
— script downloads in parallel;
— script executes after parsing.
If defer is not working, scripts may still block rendering.
Reason 1: defer on inline script
The most common issue. Defer has no effect on inline scripts.
What to check:
— is the script inline;
— does it have src;
— is defer applied.
The fix: move inline scripts to external files, or place them at the end of body.
Use JavaScript defer checker to see which scripts use defer.
Reason 2: missing src
Defer requires src. If src is missing, defer is ignored.
What to check:
— does the script have src;
— is src valid;
— is the script loaded correctly.
The fix: ensure the script has a valid src.
Reason 3: module scripts
Module scripts (type="module") are deferred by default. Adding defer may not change behavior or may be ignored.
What to check:
— is the script type="module";
— does it need defer;
— is it executing in order.
The fix: module scripts are already deferred. Remove defer if not needed, or adjust loading strategy.
Reason 4: script order issues
Deferred scripts execute in order. If a script depends on another, order matters.
What to check:
— are scripts in the correct order;
— do they depend on each other;
— is defer applied to all.
The fix: ensure scripts are in the correct order. Use defer on all scripts that need to run after parsing.
Reason 5: async instead of defer
If async is used instead of defer, scripts execute as soon as they download, which may be before HTML parsing is complete.
What to check:
— is async used;
— does the script need to wait for DOM;
— is order important.
The fix: use defer for scripts that need DOM and order. Use async for independent scripts.
How to diagnose defer issues
A practical sequence:
— check script tags;
— check for inline scripts;
— check src;
— check type="module";
— check script order;
— check async vs defer.
If defer is not working, the issue is likely inline scripts or missing src. For a broader audit, SEO audit can help verify scripts, rendering and performance in one place.
How to fix defer issues
Fix steps:
— move inline scripts to external files;
— ensure src is present;
— use defer for scripts that need DOM;
— use async for independent scripts;
— check script order;
— test after changes.
FAQ
Why is defer not working?
Most often because the script is inline, src is missing, or the script is a module.
Does defer work on inline scripts?
No. Defer works only for external scripts with src.
Do module scripts need defer?
No. Module scripts are deferred by default.
What is the difference between defer and async?
Defer waits for HTML parsing and preserves order. Async executes as soon as downloaded.
Does defer affect SEO?
Indirectly. Defer improves rendering and Core Web Vitals, which affect rankings.
Can defer break scripts?
If scripts depend on order, incorrect use can break them. Ensure order is correct.
Why do scripts still block with defer?
Check for inline scripts, missing src, or other blocking resources.
Can I use defer on all scripts?
Not always. Scripts that need to run early should not be deferred.
How do I check if defer is applied?
Inspect the HTML or use a defer checker.
What if defer works in one browser but not another?
Check browser support and script type. Module scripts behave differently.