First of all, this technique is only really applicable to apps where there's only one big HTML template which is then shuffles, part hidden and part visible thanks to lots of Javascript. Those familiar with jQuery Mobile will have seen this.

On Around The World there are a lot of images. Majority of them you don't need to see immediately because only one screen is loaded at the time. The page structure looks like this:


<div class="section" id="page1">
  <h2>Page 1</h2>
  <img src="section-icon1.png">
</div>
<div class="section" id="page2" style="display:none">
  <h2>Page 2</h2>
  <img src="section-icon2.png">
</div>
<div class="section" id="page3" style="display:none">
  <h2>Page 3</h2>
  <img src="section-icon3.png">
</div>

So, if you load that you'll notice that your browser will download "section-icon1.png", "section-icon2.png" and "section-icon3.png" even though two of the images are not going to be displayed. Good for pre-loading the images when they're later needed but bad for the user experience since the browser will be busy downloading images rather than displaying the first visible section.

This is how I solve this; first I change the HTML to be this:


<div class="section" id="page1">
  <h2>Page 1</h2>
  <img src="." data-src="section-icon1.png" class="deferred">
</div>
<div class="section" id="page2" style="display:none">
  <h2>Page 2</h2>
  <img src="." data-src="section-icon2.png" class="deferred">
</div>
<div class="section" id="page3" style="display:none">
  <h2>Page 3</h2>
  <img src="." data-src="section-icon3.png" class="deferred">
</div>

And now for the magic that turns these img tags into real normal img tags. The truth is that the Javascript about loading individual sections is a bit more complicated but in its inner core it looks something like this:


// variable 'hash' is something like 'page2'
if ($(hash + '.section').size()) {
  $('.section:visible').hide();
  $(hash + '.section').show();
  $('img.deferred', hash).each(function() {
    var el = $(this);
    el.attr('src', el.data('src'));
    el.removeClass('deferred');
  });
  ...

It makes the HTML slightly more complicated but the end result is great. It's not just useful for the first-time load but also applicable every time someone reloads the page.

Comments

Fowl

"." and "" are are valid URLs in some browsers.

You might need to do something slightly more complicated or use a "no image" image.


http://www.nczonline.net/blog/2009/11/30/empty-image-src-can-destroy-your-site/

Anonymous

Great! Thanks for the heads up

asd

the solution sucks

Your email will never ever be published.

Previous:
Postgres collation errors on CITEXT fields when upgrading to 9.1 May 21, 2012 Web development
Next:
Difference between $.data('foo') and $.attr('data-foo') in jQuery June 10, 2012 JavaScript
Related by category:
How to SSG a Vite SPA April 26, 2025 JavaScript
Switching from Next.js to Vite + wouter July 28, 2023 JavaScript
An ideal pattern to combine React Router with TanStack Query November 18, 2024 JavaScript
get in JavaScript is the same as property in Python February 13, 2025 JavaScript
Related by keyword:
More CSS load performance experiments (of a React app) March 25, 2017 Web development, React, JavaScript
To defer or to async JavaScript tags. That's the question. June 29, 2018 Web development, Web Performance, JavaScript
Images April 30, 2004 Misc. links