Async Image Decoding
Decode images off the main thread with decoding="async" to reduce jank during image-heavy scrolling.
Metrics
This technique does not move LCP.
This technique can move up to 67% of TBT's share of the Lighthouse score.
This technique does not move CLS.
This technique does not move FCP.
This technique does not move SI.
This technique does not move TTFB.
Overview
By default, browsers decode image files — converting compressed JPEG/PNG/WebP byte data into pixel buffers — on the main thread. On pages with many large images, this decoding work occupies the main thread and can cause visible jank during scrolling and interaction. The decoding="async" attribute on <img> tags tells the browser to perform image decoding off the main thread, in a background process, making the decoded pixels available when ready without blocking user interaction.
Impact grade, A+ to D: how much of the Lighthouse score this technique can move. Unaffected: LCP, CLS, FCP, SI, TTFB.
The Problem
Image decoding is computationally expensive, especially for large images. A 1200×800 JPEG requires allocating a 1200×800×4 byte (3.84 MB) pixel buffer and running decompression algorithms. When a user scrolls quickly through a gallery, blog grid, or product listing, the browser must decode dozens of images rapidly — all on the main thread. This produces frame drops, delayed interaction responses, and inflated Total Blocking Time, particularly on mid-range and lower-end mobile devices.
Performance Impact
TBT
10–40%
image decoding tasks removed from main thread reduce long task duration, especially on mobile
INP
Indirect
main thread is more available for interaction processing when decode work runs off-thread
Risk: Very Low
browser falls back to synchronous decode if needed — no visual or functional regression; avoid on LCP image
How it works
01
The browser's image decode pipeline
After downloading an image file, the browser must: allocate a pixel buffer in memory, run the format-specific decompressor (DCT for JPEG, DEFLATE for PNG), apply color space conversions, and transfer the result to GPU memory for compositing. Without
decoding="async", all of this happens synchronously on the main thread before the frame can be painted.02
async decoding uses a background thread
With
decoding="async", the browser defers the pixel decoding step to a worker thread. The main thread continues processing events and running JavaScript. When decoding completes, the pixel buffer is passed to the compositor without a main-thread pause. The image may appear slightly later in the render cycle, but interaction responsiveness is preserved.03
Applies to all image types and src attributes
The attribute works on
<img src>,<img srcset>, and<picture>elements. It does not apply to CSS background images (which use a different decode path) or to<canvas>.04
Pair with loading="lazy" for below-fold images
For images below the fold, combine
decoding="async" loading="lazy": lazy loading defers the download; async decoding ensures that when the download completes and the image enters the viewport, its decoding does not block the scroll handler.
Code Example
<img src="/product-1.jpg" alt="Product 1" width="400" height="300">
<img src="/product-2.jpg" alt="Product 2" width="400" height="300">
<!-- Default: decodes synchronously on main thread when painted --><img src="/product-1.jpg" alt="Product 1" width="400" height="300" decoding="async">
<img src="/product-2.jpg" alt="Product 2" width="400" height="300" decoding="async" loading="lazy">
<!-- Decodes on background thread; main thread stays free for interactions -->In WordPress, add via the wp_get_attachment_image_attributes filter: add_filter('wp_get_attachment_image_attributes', function($attr){ $attr['decoding'] = 'async'; return $attr; });
Limitations
- Do not apply
decoding="async"to above-the-fold images — particularly the LCP element. Async decoding may delay the initial paint of critical above-fold images, increasing LCP. Reserve it for below-fold and gallery images. - The performance benefit is most significant on mobile devices and mid-range hardware where the main thread is more constrained. On high-end desktop machines, the effect is minimal.
- Browser support is universal in modern browsers, but the attribute is a hint — the browser may choose to decode synchronously anyway if it determines async is not beneficial.
Common Mistakes
Applying decoding=”async” to the hero or LCP image
The LCP image should decode as fast as possible. Use decoding="sync" (or no attribute, since sync is the default for most above-fold images) and fetchpriority="high" on the LCP image. Reserve async for everything below the fold.
Using decoding=”async” as a substitute for lazy loading
async decoding does not defer the download — it only defers the decode step. For below-fold images, pair decoding="async" with loading="lazy" to defer both the download and the decode.