Lazy loading images if JS enabled, loading images normally if not

I have a site that uses lazy loading for images, but it doesn’t work without JS (the images are not shown) which has been bothering me.

I had a brainwave to fix this. Currently my images have a data-src but no src attribute. It occurred to me that if I gave them both and then set the src to the empty string I could have the best of both worlds.

This is my original JS (which I think came from @m3g4p0p)

var images = document.querySelectorAll("[data-src]");
var imgArray = Array.from(images);

var checkImage = function checkImage(image) {
  if (image.getBoundingClientRect().top < window.innerHeight) {
    image.src = image.dataset.src;
    return false;
  }
  return true;
};

var scrollHandler = function scrollHandler() {
  imgArray = imgArray.filter(checkImage);
  if (!imgArray.length) {
    window.removeEventListener("scroll", scrollHandler);
  }
};

window.addEventListener("scroll", scrollHandler);
imgArray = imgArray.filter(checkImage);

and I have added

var nullImage = function nullImage(image) {
  image.src = "";
};

images.forEach(nullImage);

but I’m not sure how to test it. I can see that the images are displayed whether or not JS is enabled, but I can’t see whether the images are being lazy loaded if JS is enabled.

Any ideas how to check, and thoughts as to whether this is a brainwave or a brain fart?

Hey @Gandalf, you can check the network panel of the browser dev tools to see when an image is getting loaded; as for clearing the src properties, you will see that the download will get initiated for all images on the page but cancelled right away. The thing is though that you have to load your JS after the images in order to query for the images, so I don’t think there’s a way to prevent the initial requests.

1 Like

I’m not sure I understand. Isn’t it just the HTML that needs to load before the JS, not the images themselves?

The images are HTML and the browser will start to fetch them when it sees them.

Once the JS changes the source I guess the image load will be abandoned but there will have been an initial request.

Have you tried the loading=“lazy” attribute? I’m not sure of support or if it works well but might be an easy option.

I’m not a fan of delaying image load unless they are images that are not required immediately.

3 Likes

Thanks

Hadn’t come across it before :frowning: Looks like it’s not widely supported just yet…

1 Like

Yes sorry, I meant the image elements. Thinking about it, I suppose your best bet would be to put the JS in the document head and wrap it in a DOMContentLoaded event listener so that it kicks in immediately after the HTML got parsed; this still won’t prevent the initial requests but probably cancel them as early as possible.

Oh yes, that would indeed make the JS solution obsolete. :-) Or you might still use it as a fallback if it’s not supported:

if ('loading' in HTMLImageElement.prototype) {
  // supported in browser
} else {
  // initiate JS lazy loading
}

(source)

2 Likes

Further thinking about it, an actual polyfill would have to do exactly as @Gandalf suggests – remove the original src attribute and replace it with a data-src attribute (or otherwise store the source internally)… either way, there’s no need to also maintain the data-src in the markup then:

Thanks @Gandalf and @PaulOB for the ideas! :-)

3 Likes

Best of both worlds. Great job @m3g4p0p. Thanks.

3 Likes

Have you tried the AmpProject.org? It had been taken over by Google and I had a demo of displaying thousands of images in less than a second!

https://www.johns-jokes.com/pictures-amp/1234567

Just stumbled across this article which may be of interest:

https://addyosmani.com/blog/lazy-loading/

1 Like

That doesn’t solve @Gandalf’s initial issue of images not displaying when JS is not available.

1 Like

It’s not something for this project as it’s already up and running, but I will take a look.

Try

  1. the following example

  2. Validate using Google priority validator or browser Addin (latter easier)

  3. Add images and test parameters

  4. Add videos and test parameters

Regret the delay in replying, it has been hectic.

Gandalf mentioned that no images were displayed when the “Lazy Loading” JavaScript routine was disabled. AmpProject uses JavaScript and also the following to cater for when JavaScript is not loaded:

<noscript>
  <style amp-boilerplate>
        body {
          -webkit-animation: none;
          -moz-animation: none;
          -ms-animation: none;
          animation: none;
        }
      </style>
</noscript>

I think that due to browser updates JavaScript is remarkably fragile and frequently fails which no doubt caters for the majority topics on this forum.

The AmpProject Team ensure that when JavaScript is not loaded the page “fails gracefully” otherwise the following large clients would raise complaints:

The Washington Post, BBC, Vox, and The New York Times

1 Like

OK, thank you.

I was basing my comment on the example link you gave:

1 Like

I just checked with Firefox’s JavaScript disabled and most surprised to discover the thumbnails are not showing :frowning:

I will investigate tomorrow and perhaps report to the AmpProject developers.

1 Like

I checked the following which looks as though I disregarded and just used the JavaScript script:

https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml/

and noticed the following must be added:

<noscript>
Allowed. Can be used anywhere in the document. If specified, the content inside the <noscript> element displays if JavaScript is disabled by the user.

So I modified the following PHP script and added <noscript>

if(0):
  // OLD SCRIPT THAT FAILS WHEN JavaScript DISABLED
$result = <<< ____EOT
  <div class="fll tac">
         <a href="$url" title="$title"> 
          <amp-img 
            src="$thumb" 
            {$dims[3]} 
            alt="$title"
          />
         </a>
         <br>
         $title 
        </div>
____EOT;

else:
// NOW WORKS OK EVEN IF JavasScript IS DISABLED
   $result = <<< ____EOT
    <div class="fll tac">
     <a href="$url" title="$title"> 
      <amp-img 
        src="$thumb" 
        {$dims[3]} 
        alt="$title"
      />
      <noscript>
        <img src="$thumb" {$dims[3]} alt="AMP">
      </noscript>
      </a>
      <br>
      $title 
    </div>
____EOT;

endif;

To test I disabled FireFox’s JavaScript:

  1. In Firefox, type “about:config” in the address bar, then press “Enter“.
  2. Select the “I accept the risk!” button.
  3. Type “javascript” in the “Search” box.
  4. Double-click the “javascript. enabled” line to toggle the setting between “true” and “false” as desired.

Online Test

Try the following where the trailing numeric parameter is the number of thumbnails to display - there is a couple of thousand and takes an extra ten seconds to display with JavaScript disabled :frowning:

https://www.johns-jokes.com/pictures-amp/10000

I use plugin, JS enabled function and it solve my issues that is website speed is down and after using the plugin my speed increases in both desktop and mobile devices.

Hi @manjulaagarwal1955 and a warm welcome to the forum.

The problem with using AmpProject is that when a user has JavaScript disabled then the images do not show.

I think it is impossible for server side PHP to detect if JavaScript is disabled so PHP just generates the page regardless.

Hello John, Yes in that manner you are right, PHP just generates the page regardless. because if Javascript is disabled then images can’t be shown and Plugins are also not able to track that images.

1 Like