Loading images only when (or if) they are needed

Images placed inside the <details> HTML element with the attribute 'loading="lazy"' won't be loaded by the browser until (or if) the user selects to expand the <summary> section. This can mean faster page loads and an improved user experience, especially if the page includes many “optional” images.

Background

I recently created a subscribe page (which can be reached from the RSS link on the homepage). The aim was to create an easy way for users to copy the RSS feed URL (previously the link simply opened the RSS feed, which many users might have found confusing), and also gives some basic instructions on how to subscribe to OnlyRSS via two popular RSS aggregators i.e. Feedly and Inoreader. The Feedly and Inoreader instructions are both displayed as ordered lists, but I also wanted to include an animated GIF showing the subscription process for each app.

The problem

The problem I encountered was that each GIF was quite large (both in terms of page real estate and file size) and users who are already familiar with RSS probably wouldn’t need to view the animations at could be considered complementary to the ordered lists, furthermore, it’s unlikely that a user would want to view the animation for both Feedly and Inoreader.

Loading both animations would not only be wasteful (in terms of page resources), but given the large vertical size of each image, the first image (for Feedly) would push the second image and instructions (for Inoreader) below the fold, where they could potentially be missed by users entirely.

What I wanted was to hide the animations from the user, and for the browser to hold-off downloading them until they were required (if at all). And I wanted this to be as seamless as possible i.e. I wanted to avoid modals and opening new tabs etc. And, of course, I wanted to avoid using JavaScript (because I don’t know JavaScript).

The solution

I’ve already used a non-JS method for hiding content until it’s requested by the user on the Changelog page i.e. the <details> and <summary> HTML elements. So I decided to use these elements with the summary text of 'Show me how', which when clicked would display the contents of the <details> element i.e. the animated GIF. You can see this in action for a static image by clicking on the text below to display Figure 1.

Figure 1: click to
A side-by-side comparision of 2 versions of the same page. In the first version, 2 large images are clearly visible, and the page is very long. In the second version no images are visible, and the page is compact.
The original Subscribe page (left) alongside the final Subscribe page (right).

The HTML required to display the “Figure 1:click to open/close” above is shown below:

<details>
  <summary>Figure 1: click to</summary>
  <figure>
    <img src="/images/subscribecompare.webp" width="800" height="1059" loading="lazy"/>
    <figcaption>
      The original Subscribe page (left) alongside the final Subscribe page (right).
    </figcaption>
  </figure>
</details>

The required CSS:

article summary {
  cursor: pointer;
  color: #0f5474;
}

/* append "open" to the end of summary text when closed */
article summary::after {
  content: " open";
}
/* append "close" to the end of summary text, when details is open */
article details[open] summary::after {
  content: " close";
}

This solved the problem of the Feedly animation pushing the Inoreader animation and instructions below the fold, but it didn’t help with page performance, as both animations were still being loaded by the browser.

I’d previously used the image attribute 'loading="lazy"' to improve page performance by letting the browser decide if an image needed to be loaded e.g. was the user close to scrolling to the part of the page that contained the image? I didn’t expect this to influence images hidden within the <details> element—I was wrong. After applying 'loading="lazy"' to both animations, they were no longer loaded by the browser until the user clicked on the summary text. This was exactly the solution I was after.

With this solution in place the subscribe page loads quickly—around 40ms—with all the content being above the fold, and the animations only loading if the user selects the relevant summary text.

Conclusions

The solution I’ve described above is probably suitable for instructional pages where the reader would only be interested in one of many options e.g. Those explanation pages that show you how to perform some complex tasks in Excel but give you four versions of the solution, one for each recent version of Excel. In that type of scenario, hiding and delaying the load of any associated images makes a lot of sense, it condenses the page (so it looks more appealing) and improves page performance.

As I’ve mentioned before, I’m not a dev, and I’m still new to HTML & CSS, so I might well look back on this post in a few months’ time and cringe due to its naivety. There’re probably far easier methods to hiding (and delaying the loading of) images than what I’ve described above, but hey, we learn better from our mistakes, so if I do come across a better solution, I’m guessing I won’t forget it :-)