← All insights

WordPress 5.5 native lazy-loading: what changes for image-heavy sites

WordPress 5.5 dropped native lazy-loading on August 11. Here is what it does, what it does not do, and the plugins you can finally retire.

WordPress 5.5 shipped today with native lazy-loading on every img tag the platform generates. This is a meaningful release for any site with heavy image content — which, on the open web, is most sites. It is also a release that has been talked about in conflicting ways, so this post is a plain explanation of what actually changed and what it means for production sites.

What 5.5 actually does

Starting in 5.5, WordPress automatically adds loading=’lazy’ to img elements rendered through the_content(), get_avatar(), wp_get_attachment_image(), and the comment system. The attribute tells the browser to defer loading the image until the user is about to scroll near it.

The browser then handles the actual lazy-loading natively. There is no JavaScript involved. There is no intersection observer wired up by WordPress. The browser decides, based on its own heuristics, when to start loading each image.

The feature works in Chromium-based browsers — Chrome, Edge, Opera, Brave — as of Chrome 76 last year. Firefox shipped support in 75 this April. Safari does not support loading=’lazy’ yet on iOS, though support is in the technology preview. For browsers without support, the attribute is ignored and the image loads as normal.

What it does not do

This is where most of the confusion lives. The 5.5 implementation has explicit limits.

First, it only adds the attribute to images that have explicit width and height in the markup. If your theme prints img tags without dimensions — which a lot of older themes do — those images do not get the lazy attribute. This is a correctness decision. Lazy-loading an image without known dimensions causes layout shifts as the image pops into the page. WordPress correctly refuses to do that.

Second, the feature does not lazy-load background images. If your theme uses background-image: url(…) in CSS, that is not an img tag and the browser cannot lazy-load it through this attribute. You need a different approach — usually picture elements or a small intersection-observer fallback.

Third, the feature does not lazy-load iframes. There is browser support for loading=’lazy’ on iframes in Chromium, but WordPress 5.5 does not add it. It might in a future release.

Fourth, the feature only handles images in post content and avatars. If you have custom theme templates that print img tags directly — gallery shortcodes that bypass the_content, page templates that print hero images, custom widgets — those images need explicit loading=’lazy’ attributes in your template code.

The plugins you can retire

For most sites, this release deprecates the dedicated lazy-loading plugins. Lazy Load by WP Rocket, a3 Lazy Load, and a half-dozen others were doing the same job in JavaScript that the browser now does natively. If your site uses one of those plugins, you can probably remove it after 5.5.

The caveat: those plugins also typically handle iframes, background images, and edge cases like avatars-in-comments before WordPress 5.5 did. If you remove the plugin, you lose those edge-case handlers too. For a clean transition, check what the plugin was actually doing on your specific site and replace anything that is not covered natively.

The image-size opportunity

5.5 also tightens up the srcset and sizes attribute handling that has been in WordPress since 4.4. The combination of accurate srcset, accurate sizes, and native lazy-loading is what makes a content-heavy WordPress site fast on a phone in 2020.

For sites that have not done a clean audit since 4.4, this is a good month to fix the regenerate-thumbnails situation. Bad sizes attributes — typically a hard-coded 100vw on every image regardless of layout — cause the browser to download an image that is too large for the actual rendered slot. Combined with lazy-loading, the browser is now smart enough to download exactly the right asset, in the right size, at the right time. But only if the sizes attribute is correct.

The above-the-fold trap

One thing to flag explicitly: the largest contentful paint image — the big hero, usually — should not be lazy-loaded. If it is, the browser delays the load until the layout is ready, and you have just added 300 milliseconds to your LCP.

WordPress 5.5 applies loading=’lazy’ to every img through the_content() automatically. If your hero image lives in the post content, it gets lazy-loaded too. The fix is either:

  • Move the hero image out of post content and into the template, where you can omit the loading attribute (or set it explicitly to ‘eager’).
  • Use the new wp_lazy_loading_enabled filter to exclude the first image in a post.

We prefer the second on content-heavy sites because it does not require editorial workflow changes. The filter takes a default value and lets you return false for the cases where lazy-loading is the wrong call.

Real-world impact

We pushed 5.5 to a test client this morning — a 600-post blog with three to ten images per post, average post weight of 1.4 megabytes before the update. Initial transfer on a typical post page dropped from 1.4MB to 380KB. Time-to-interactive on a mid-range Android phone dropped from 4.2 seconds to 2.6. LCP held steady because the hero image was correctly excluded from lazy-loading.

This is the kind of release where you do not need to do anything for most of the benefit to show up. Update, regenerate thumbnails if you have not in a while, and let the browser do the work. For sites where the gains matter more than the defaults can deliver, the manual tuning is straightforward.

Pick a stack. Or pick the team that ships every one of them.