HomeMethod

Knowledge

Web VitalsTechniquesSnippetsAnswersImpactsBottlenecks

Async Image Decoding

Decode images off the main thread with decoding="async" to reduce jank during image-heavy scrolling.

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

  1. 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.

  2. 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.

  3. 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>.

  4. 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

Before
<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 -->
After
<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.

Test this techniqueImage DiagnosticsRun the tool

Targeted fixes, not guesswork.

Start an Engagement
Support our family now