I know that (a handful of) non-JavaScript users are out there and I'd like to cater for them instead of giving them poorer experience just because of their preference (be that for privacy reasons or whatever).
Most lazy-loading JS libraries seem to address this in the same fashion, for example see lazysizes:
<style>
.no-js img.lazyload {
display: none;
}
</style>
<noscript>
<img src="image.jpg" />
</noscript>
<img src="grey.jpg" data-src="image.jpg" class="lazyload" />
Mainly out of curiosity, I got to wondering if it would be possible to pull the fallback out of the <noscript>
tag and add it to the DOM programmatically with JavaScript so that the image source didn't have to be duplicated in two image tags which would leave me with just:
<noscript>
<img src="image.jpg" class="lazyload" width="600" height="400"/>
</noscript>
Here's what I've knocked together:
(function(attribute) {
Array.prototype.forEach.call(document.getElementsByTagName("noscript"), function(node) {
var parser = new DOMParser,
el = parser.parseFromString(node.textContent, "text/xml").documentElement, // XML => <img/> required
img = ("img" == el.tagName) ? el : el.getElementsByTagName("img")[0]; // allow for <img/> in <picture>
img.setAttribute(attribute, img.getAttribute("src"));
img.setAttribute("src", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC");
node.insertAdjacentHTML("beforebegin", el.outerHTML);
});
})("data-src"); // different libraries use different data attribute names
This appears to work everywhere (Chrome, Safari, Opera, Firefox) except Internet Explorer (naturally). I know that .textContent
isn't available pre-IE9 but IE9+ all seem to be failing at the final hurdle - the .outerHTML
. Am I doomed to failure and having to repeat myself in my markup?
Update: To clarify, I'd ideally like to be able to use arbitrary attributes (alt, title, etc.) in the image tag or even use responsive markup:
<noscript>
<picture>
<source ... />
<source ... />
<img src="image.jpg" />
</picture>
</noscript>
Lazy Loading Images is a set of techniques in web and application development that defer the loading of images on a page to a later point in time - when those images are actually needed, instead of loading them up front.
IMG tags can leverage native browser lazy loading, which doesn't require any JavaScript. You can still lazy load background images if they're in HTML as an inline style.
Lazy loading is the practice of delaying load or initialization of resources or objects until they're actually needed to improve performance and save system resources.
If you're not sure if lazy loading is working correctly, you can open the Chrome DevTools and check that the images are not loaded until the scroll. Here are the steps you should take: Open the Chrome DevTools, go to the Network tab and the Img filter. At this point, reload the page.
I'm the creator of lazySizes. This approach has multiple porblems:
noscript
element is never renderend, which means it is not detectable, wether it is visible or not (or better said it is always invisible)lazyloading
and lazyload
to give feedback to the userdata-sizes="auto"
feature can't be usedHowever if 4. and 5. isn't a problem for you, it is possible to use a noscript
child element in conjunction with a lazyload
parent to achieve this.
The markup could look something like this:
<div class="lazyload" data-noscript="">
<noscript>
<p>any kind of content you want to be unveiled</p>
</noscript>
</div>
And the lazySizes plugin code would look something like this:
(function(){
'use strict';
var supportPicture = !!window.HTMLPictureElement;
addEventListener('lazybeforeunveil', function(e){
if(e.defaultPrevented || e.target.getAttribute('data-noscript') == null){return;}
var imgs, i;
var noScript = e.target.getElementsByTagName('noscript')[0] || {};
var content = noScript.textContent || noScript.innerText || '';
e.target.innerHTML = content;
if(supportPicture){return;}
imgs = e.target.querySelectorAll('img[srcset], picture > img');
for(i = 0; i < imgs.length; i++){
lazySizes.uP(imgs[i]);
}
});
})();
In case you like this, I might make an official plugin for this. Here is the plugin: https://github.com/aFarkas/lazysizes/tree/master/plugins/noscript
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With