WordPress.org

Make WordPress Core

Opened 4 weeks ago

Last modified 6 days ago

#44427 new feature request

Introduce lazy-loading API for media and other elements

Reported by: mor10 Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: Media Keywords:
Focuses: Cc:

Description

Synopsis

Lazy-loading of media and other elements (iframes, embeds, etc) is a performance best practice. Currently, various plugins including Jetpack, and themes including WP Rig ship lazy loading features to improve performance. These solutions rely on conditionally rewriting the HTML for images and other media as it is being loaded from core which is sub-optimal.

Proposal

Introduce a lazy-loading API in core which lazy-loads media and other elements out of the box based on various conditions, with an opt-out feature in the Customizer. This takes the onus of having extensive knowledge of performance optimization and how to add lazy-loading to your site off the shoulders of the end-user and gives developers control over how and when content is lazy-loaded.

The lazy-loading API should allow theme- and plugin developers detailed control over how lazy-loading works. As an example, the AMP plugin would disable core lazy-loading and replace it with its own custom method. Another example: A theme developer may choose to immediately load the featured image of the first post in an index or archive template while all other images are lazy-loaded.

Why this isn't plugin territory

Lazy-loading is currently considered plugin territory. I disagree for a couple of reasons:

  1. Lazy-loading is performance best-practice: https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video/.
  2. WordPress should not put the onus on site-owners to have in-depth knowledge of performance best-practices and how to meet them.
  3. With no consistent API, plugins and themes may introduce different and conflicting solutions to the same problem which in turn causes unexpected behavior for the end-user.
  4. Lazy-loading introduced at plugin/theme level forces aggressive rewriting of content which would be more consistently performed at core.

Change History (3)

#1 @tabrisrp
4 weeks ago

As the developer of a performance optimization plugin, I definitely relate with points 3 and 4, which are recurring issues for both our development & support teams.

Having a standardized lazy-loading API in core would greatly reduce the conflicts we encounter, and reduce our need to consistently & accurately parse the HTML content of pages to detect and rewrite lazy-loadable media assets.

I believe it would also help solve difficult situations like lazy-loading background images, a common user-requested feature, which is hard to get around without a core standard.

#2 follow-up: @jonoaldersonwp
4 weeks ago

This feels like a great win for performance, standards, carbon, etc. The SEO and performance nerd in me loves this.

Is there any reason why we can't/shouldn't implement this, verbatim, as per the Google documentation (using the event handlers method, until such time as the intersection observer method is universally supported)?

Given how minimal the JS size and processing overhead is, and given that we'll want lazy-loading to be default on (at least, in future/ongoing theme dev etc), I've no objections to the JS being autoloaded on all front-end requests (unless it's specifically disabled/de-enqueued).

I do think that there may be some nuance in implementation; some scenarios:

  1. Inline images, inserted in content; where we'll be adding a bunch of data- params to the code. We'll need any existing or new filtering/validation to anticipate and manage this (or, to transform the code via a filter on the_content, if we're concerned about code bloat or confusion in the content editor).

1a) Gutenberg blocks.

1b) images in non-webpage context / where js isn't available, like REST or RSS.

  1. Theme/template images which use wp_get_attachment_image() or similar to output image HTML. We'll need to hook into these with an additional parameter (we shouldn't make this a universal default/assumption, as many themes use 'hero images' in header areas where lazy-loading may produce an unwanted delay).
  1. Theme/template images which use wp_get_attachment_image_srcset() or similar to construct the output of the img/picture etc tag. This poses a challenge.

The first and the second feel achievable; some settings, an extra parameter in the case of 2, and everything else can happen under the hood.

The third feels like the messiest for easy adoption; we're relying on a significant change to coding approaches, which @mor10 rightly wants to avoid. Thoughts appreciated!

Last edited 4 weeks ago by jonoaldersonwp (previous) (diff)

#3 in reply to: ↑ 2 @flixos90
6 days ago

Is there any reason why we can't/shouldn't implement this, verbatim, as per the Google documentation (using the event handlers method, until such time as the intersection observer method is universally supported)?

I like this idea, relying on a method that has been recommended by one of the expert sources in the field seems like a solid approach to me. We might even implement both ways in one script, and only execute the modern one if "IntersectionObserver" in window. Otherwise use the event listener one.

Before we dive into implementation further, I think we need to discuss how this should integrate with themes.

  • Given the need for some images to always load immediately and skip lazy-load, I suggest we only lazy load when the theme does add_theme_support( 'lazy-load' ). While this will result in adoption of lazy-loading not drastically increasing immediately, experience has proven that, over time, most theme features introduced were at a certain point commonly supported by most themes (think about title-tag for example). We just need to document well, make supporting the feature easy and encourage it. I think by making it opt-in, we're on the safe side. Also, some themes include this already, and there are plugins implementing that, so with opt-in we ensure that there are no conflicts for those sites.
  • I think we should only account for what we can reasonably account for. <img> tags in filterable content should be adjusted, as well as any calls to wp_get_attachment_image(). However, when people use other techniques (i.e. "hard-code" the <img> tags themselves, what you @jonoaldersonwp mentioned too), we shouldn't automatically touch this, as it would require some output buffering, which we should avoid IMO. Documentation should rather highlight that this way of including images is not recommended and wp_get_attachment_image() should be used instead. Something I'm not sure about is how to deal with background images as there's no standardized way of having that markup generated (also it's only markup if through an inline style attribute, otherwise in a CSS file, which makes this more tricky).
  • We need to figure out a way to easily allow theme developers to indicate that specific images must not be lazy-loaded. This could mean having a specific CSS class for this, or such thing as a data-skip-lazy-load attribute. Possibly, we could allow content creators to handle this as well, by putting a checkbox into the "Insert Media" modal somewhere, which says "Skip lazy-loading for this image?" - and if so, put the class or attribute into the generated tag.
Note: See TracTickets for help on using tickets.