Angular @defer: Lazy-Load Template Blocks with Triggers (@placeholder, @loading, @error)
Quick answer
Angular's @defer block lazy-loads a section of a template until a trigger fires — on viewport, on interaction, on hover, on idle (default), on immediate, on timer(...), or when a condition is true. Its component dependencies are split into a separate chunk, so non-critical UI stays out of the initial bundle. Pair it with @placeholder, @loading, and @error blocks to control what renders before, during, and on failure. Note: @defer is a block (@defer { }), not a *defer directive.
Short answer: @defer is a template block (@defer { … }, not a *defer directive) that lazy-loads its content — and code-splits its dependencies — until a trigger fires (on viewport, on interaction, on idle, on hover, on timer, or when a condition). Pair it with @placeholder, @loading, and @error.
@defer is Angular's built-in way to keep non-critical UI out of the initial bundle. The critical detail most write-ups get wrong: it's a block, not a directive — there is no *defer.
Basic usage with all four blocks
@defer (on viewport) {
<heavy-chart [data]="data" />
} @placeholder {
<p>Chart loads when you scroll to it</p>
} @loading (minimum 1s) {
<spinner />
} @error {
<p>Couldn't load the chart.</p>
}@defer— the deferred content; its components are split into a separate chunk.@placeholder— shown until the trigger fires (required to use theon viewport/on interaction/on hovertriggers).@loading— shown while the chunk downloads;minimum/afterparams prevent spinner flicker.@error— shown if loading fails.
Triggers
@defer (on idle) { … } <!-- default: when the browser is idle -->
@defer (on viewport) { … } <!-- placeholder scrolls into view -->
@defer (on interaction) { … } <!-- user clicks/keys the placeholder -->
@defer (on hover) { … } <!-- pointer over the placeholder -->
@defer (on immediate) { … } <!-- as soon as rendering finishes -->
@defer (on timer(5s)) { … } <!-- after a delay -->
@defer (when isReady()) { … } <!-- when a condition becomes true -->Prefetch: download early, render later
Fetch the chunk ahead of time without rendering it yet, so it's ready the instant the trigger fires:
@defer (on interaction; prefetch on idle) {
<comments-panel />
} @placeholder {
<button>Show comments</button>
}Trade-offs and the SEO caveat
- Reduced initial bundle / faster first load — the deferred chunk isn't downloaded until needed.
- SEO caveat — deferred content is not in the initial render, so crawlers may not see it until the trigger fires. Defer genuinely non-critical, below-the-fold UI; keep must-index content outside
@defer. - Standalone deps — the components inside
@defershould only be referenced there, so Angular can safely split them into their own chunk.
Common interview traps
<div *defer>— invalid;@deferis a block, not a directive.- Forgetting
@placeholder— required for the interaction/viewport/hover triggers. - Deferring above-the-fold or must-index content — hurts UX/SEO.
Related guides
Sources
Key takeaways
- •@defer is a template BLOCK — @defer { } — not a *defer directive (that syntax does not exist).
- •Triggers: on idle (default), on viewport, on interaction, on hover, on immediate, on timer(5s), or when <condition>.
- •Deferred dependencies are code-split into their own chunk, shrinking the initial bundle.
- •@placeholder, @loading, and @error blocks control the before/during/failure UI; @loading and @placeholder take timing params.
- •Use prefetch (e.g. prefetch on idle) to fetch the chunk early but render it later; and remember deferred content isn't in the initial render (SEO caveat).
Frequently asked questions
What is @defer in Angular used for?
@defer lazily loads a block of a template — and code-splits its component dependencies into a separate JavaScript chunk — until a trigger fires. It keeps non-critical content (charts, comments, below-the-fold widgets) out of the initial bundle, improving initial load time.
What triggers can @defer use?
on idle (the default), on viewport (when the placeholder enters the viewport), on interaction, on hover, on immediate, on timer(duration), and when <boolean expression>. You can also add prefetch with its own trigger to download the chunk ahead of rendering.
Does @defer hurt SEO?
It can for the deferred content specifically, because that content is not in the server-rendered/initial HTML — a crawler may not see it until the trigger fires. Defer genuinely non-critical, below-the-fold UI; keep content you need indexed outside the @defer block.
Software Engineering Leader & Technical Author · Updated August 26, 2026