Using native Lazy-Load, no need Lazy-Load JS Library?

Safari-native-LazyLoad-iPhone-setteing[catch-image]

I still see a lot of articles about "native Lazy-Load of Safari browser does not support iframe elements (tags)"...

 "Safari 16.3 or earlier"  is already supported for iPhone, iPad, and Mac with optional settings, so don't make a mistake❗️

( Now that IE is no longer supported ) New versions of major browsers have completed native Lazy-Load support .
( including WebP image support )

But if we use the browser's "native Lazy-Load", do we not need "Lazy-Load JS Libraries" anymore


  In Safari 16.4 (released 2023-03-27) and later , "Native Lazy-Load" supports <iframe> by default , in addition to <img> ‼️ 



 An "article" for beginners, has been added to ❗️
If your PSI Performance Score is less than 80...
 ( Article in Japanese )




Major browsers already support native Lazy-Load

 ( Now that IE is no longer supported, )
Newer versions of modern browsers should support native Lazy-Load.
 ( including WebP image support )



Finally, Safari browser now supports native Lazy-Load

  In Safari 16.4 (released 2023-03-27) and later , "Native Lazy-Load" supports <iframe> by default , in addition to <img> ‼️ 


However  Safari16.3 or earlier , by default, only the img element is supported, so an optional setting is required to support the iframe element:‼️

 Safari16.3 or earlier , "native Lazy-Load support for img + iframe elements" is already supported on iPhone, iPad, and Mac, although optional settings are required❗️


iPhone / iPad 】 

  1. Open the "Settings" App
  2. Scroll down to the "Safari" menu item and tap it
  3. Tap the "Advanced" menu item
  4. Tap the "Experimental Features" menu item
  5. Enable the two radio buttons as shown in the "Experimental WebKit Features" screen below❗️
    • Lazy iframe loading
    • Lazy image loading
Safari-native-LazyLoad-iPhone/iPad-setteing

Mac 】 

  1. Open "Safari" application, on your macOS computer
  2. Click on the "Safari option" in the top left corner of the application and select the "Preferences" option from the drop-down menu
  3. Next, go to the "Advanced" section and enable the "Show Develop menu in menu bar" option by checking the box
  4. Finally, click on the "Develop" menu from the top menu bar and enable the "two checking boxes" from the "Experimental Features" section as shown in the screen below❗️
    • Lazy iframe loading
    • Lazy image loading
Safari-native-LazyLoad-Mac-setteing


Advantages of "native Lazy-Load"

Just add the loading="lazy" attribute

Just add the following attributes to  <img>   <iframe>  tags" ‼️

( However, you need to set the size of the target element with "height / width" attribute or inline-CSS )

 loading="lazy" 

This is all it takes for the data to be downloaded and displayed as it scrolls by and the target element appears in the screen area .



With WordPress, it's automatically applied

That means you don't even have to add  loading="lazy" ‼️ 

Since WordPress 5.5, it is automatically applied to img elements, and then to iframe elements as well .
( However, it is necessary to set the size of the target element using the height and width attributes or inline-CSS )

The first img and iframe elements on the page are automatically non-applied, but manual adjustment may be required to completely deal with the first view ...



No need to add JS library

Although it is necessary to add loading="lazy" ( WordPress does not require it ), "native Lazy-Load" is realized only by browser functions, so there is no need to add a new JS Library to your site .



"native Lazy-Load" is possible even when JS is disabled

Because it does not depend on JavaScript, "native Lazy-Load" can be displayed lazily even when JS is disabled !

If you are preparing for browsing from PC and smartphones with "JS disabled", "native Lazy-Load" is the only choice because the JS library does not work when JS is disabled .



noscript element and "meta refresh"


This site has given up viewing when JS is disabled, so use the  <noscript>  element to redirect .

The sample code to redirect to another page "that prompts to enable JS" after 3 seconds when JavaScript (JS) is disabled is shown below .
In fact, if you switch the browser setting to "Disable JavaScript" and super-reload the browser, the redirect screen will be displayed.

If you go back to the "previous page" (because JS library does not work of course), the screen should be displayed in the original state (using native Lazy-Load) as described in the posted article .

<head>
  <!-- Omission -->

  <!-- When JavaScript is disabled, a "page prompting to enable JS" is displayed after 3 seconds -->
  <noscript>
    <b:if cond='data:blog.url != &quot;https://www.gadgets-geek.net/p/noscript.html&quot;'>
      <meta content='3; URL=/p/noscript.html' http-equiv='refresh'/>
    </b:if>
  </noscript>

</head>

The  <noscript>  elements is executed only when JavaScript is disabled .

 Line 7:  <meta>  elements must be placed in the <head> element, not in the <body> element, to be executed
 Lines 6 and 8: Conditional branching if statement to "execute line 7 only if the URL is different from the redirect URL"
 (For Google Blogger blogs)


※ Change to a <noscript> sample that displays a message at the top of the page ,
since  meta refresh  raises a "warning" in the "Microsoft Bing Webmaster Tools" .

<body>
  <noscript>
  <p style='margin: 1rem;'>
  <font color='red' size='6'>
    <b>JavaScript has been "disabled" !!</b><br/>
    <a href='/p/noscript.html'><b><i>Click THIS</i></b></a><br/>
    <b>Please enable JavaScript !!</b>
  </font>
  </p>
  </noscript>

  <!-- Omission -->

</body>


Disadvantages of "native Lazy-Load"

Only "img and iframe" elements (tags) are supported

Because only both elements are supported,  "Lazy Load" of  <code>  elements with source code display libraries such as "Prism.js" and "highlight.js"  , is not supported.


There is no problem with "YouTube" and "Google Maps" because they use static iframe elements .
However, as of the end of February 2023, the following  SNS embedding, in which an iframe element is dynamically generated  after the specified JS is executed, is not supported.

Theoretically, it should be possible to automatically add the loading="lazy" attribute to the dynamically generated iframe element, but I think it is difficult to know when Twitter is dynamically generated...

  • Twitter tweet embed code blockquote element ➡️ div element containing iframe element
  • Twitter timeline embed code  a  element ➡️ div element containing iframe element
  • Instagram embed code blockquote element ➡️ iframe element
  • TikTok embed code blockquote element ➡️ iframe element


Detailed settings are not possible because the function is dependent on the browser

The only option available is to start rendering as soon as the target element appears on the screen .
Currently, it is not possible to set the "delayed loading timing", such as starting rendering before or after the element enters the screen area .

If network speeds and PC processing power increase dramatically, this may not be a problem (since the display is instantaneous) .



In Safari browser, with default settings, only the img element is applied

  Native Lazy-Load" will support <iframe> default in addition to <img> in Safari 16.4 and later, released 2023/03/27‼️ 


native Lazy-Load is a browser-dependent feature, so if it is not applied in the browser settings, "Lazy Load" will not be reflected .
If "Lazy Load" is performed by a JS Library, it is often implemented in such a way that it does not depend on the browser settings...

 Safari16.3 or earlier , Safari browsers on iPhone, iPad, and Mac devices  require an optional setting for iframes to be native lazy-loaded: ‼️ 

 Safari16.3 or earlier , every time a new version of Safari is released (and reset), the options must be set each time .
Therefore, iPhone and iPad need to be reconfigured at least every time a major release of iOS / iPadOS is made .

If the browser does not support it or does not apply it, the loading="lazy" attribute is ignored and "Lazy Load" is not applied, but the element itself is displayed .




Need for Lazy-Load JS Library (Hybrid)

Recommend using "native Lazy-Load" and "JS Library" in combination


 If only "static img + iframe" elements are to be lazy-loaded, the browser's "native Lazy-Load" will do the job. (See here for details) . 

However, it is not possible to configure or customize it in detail .

Otherwise,  you still need to rely on plug-ins, JS libraries... 


However, in the case of a browser with JS disabled, "JS library only" will not display anything or only display low-resolution images,  so it is advisable to use both ‼️ 

(1) If you write "loading="lazy" attribute in img or iframe tag in your post, native lazy-laod will be applied even if JS is disabled, and it will be the best display .
 (In the case of WordPress, "loading="lazy" is automatically added except for img and iframe tags at the beginning of the page )

(2) The conditions for applying the JS Library, such as setting data-src attribute and adding CSS classes, can be done in JavaScript: ‼️



JS sample that rewrites "native Lazy-Load" to support JS Library

As a prerequisite, the loading="lazy" attribute must be added to the img and iframe tags of the posted article so that "native Lazy-Load" is used even when the browser has JS disabled‼️
( Since WordPress version 5.9, the loading="lazy" attribute is automatically added to both elements, and only the first element on the page is automatically excluded . )

 If you don't write the HTML code for JS Library in a posted article, you don't need to rewrite a posted article even if you want to "switch JS Library" or "discontinue JS Library"


 Sample code to rewrite img + iframe elements using "native Lazy-Load", to the JS Library version 

(Note) The DOM in memory is rewritten instead of rewriting a posted article .

・Only img / iframe elements with the loading="lazy" attribute are extracted .
・If you use srcset attribute or <picture> element, you need to modify it❗️



(1) Copy the value of the src attribute (URL) to the data-src attribute
(2) Set a "BASE64-encoded transparent GIF image" to the value of the src attribute of the <img> element
(3) Set "about:blank" to the value of the src attribute of the <iframe> element
(4) Delete the loading attribute and add any CSS class names to the <img> / <iframe> element



If the image server returns a "low-resolution image" with only a parameter change (as in the Google Blogger blog) , you can replace (2) by setting "low-resolution image" ( parameter substitution using a regular expression ) .

If you delete line 13 and add node.classList.add("xxx"); one line after lines 8 and 10, you can add different CSS class names for img and iframe .
"lazyload-img" , "lazyload-iframe" and so on...

You can extract the target elements with querySelectorAll() if the argument is a "Lazy-Load JS Library" with a node list (element array) , or with getElementsByClassName() if the argument is an HTML collection .
Lines 17 and 18 show an example of using the Defer.js library's function to lazy-load elements whenever they appear during scrolling .

const nodes = document.querySelectorAll('img[loading="lazy"], iframe[loading="lazy"]');

nodes.forEach(function(node) {
  if ( !(node.tagName === 'IMG' || node.tagName === 'IFRAME') ) return;
  if ( !node.hasAttribute('src') ) return;
  node.setAttribute('data-src', node.src);
  if (node.tagName === 'IMG') {
    node.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
  } else {
    node.src = 'about:blank';
  }
  node.removeAttribute('loading');
  node.classList.add('my-lazyload');
  //console.info(node);	//for Debug
});

Defer.dom('img.my-lazyload', 0, null, null, {rootMargin: "100%"});
Defer.dom('iframe.my-lazyload', 0, null, null, {rootMargin: "120%"});

① The argument of the first line is a CSS selector (string) , so if necessary, limit it to the parent element as follows .
In the theme I use, the "entry-text" CSS class is added to the div parent element of the post article section...
 '.entry-text img[loading="lazy"], .entry-text iframe[loading="lazy"]'

② Add arbitrary CSS class names to make it easy to extract elements to which JS Library is applied .
 (Note) If JetTheme theme has Defer.js from the beginning and Defer.dom() function is called (to prevent double applying), CSS class name of "lazyload" should be avoided .

③ The first argument of the Defer.dom() function in the Defer.js library is a CSS selector (string) .
 For the same condition, "img.my-lazyload, iframe.my-lazyload" can be written together in one line .



 As an added bonus, here is the code to replace CSS class names: ‼️ 
Twitter and Instagram lazy-load all target elements at once when the specified JS is executed, so "troublesome handling" is required to lazy-load each time a target element appears by scrolling .
To achieve this without using the API, the "specified class name" must be changed to avoid batch lazy-load, and then the loop processing must be done on your own .

(Note) The querySelectorAll() function returns a Node list, so it can be looped through with forEach, but if an HTML collection such as the getElementsByClassName() function is returned, it must be looped through with for .
( The forEach loop can also be used if it is handled indirectly as an array . )

If you are also interested in the difference between a "node list" and an "HTML collection" ...

const tw_EmbedTW = document.querySelectorAll('.twitter-tweet');
const tw_EmbedTL = document.querySelectorAll('.twitter-timeline');
const instaEmbed = document.querySelectorAll('.instagram-media');

tw_EmbedTW.forEach(function(node) {		// Twitter TWeet
  node.classList.replace('twitter-tweet', 'lazy-tweet');
});
tw_EmbedTL.forEach(function(node) {		// Twitter TimeLine
  node.classList.replace('twitter-timeline', 'lazy-timeline');
});
instaEmbed.forEach(function(node) {		// Instagram
  node.classList.replace('instagram-media', 'lazy-instagram');
});

After loading the specified JS, the basic function is as follows ...
 In the case of Twitter, twttr.widgets.load(element);
 In the case of Instagram, instgrm.Embeds.process(element);
Although this can be possible by looping through each of the above functions, the actual code is complex because the elements are generated dynamically .



If you use WordPress, you can use a plugin...

If you do a Google search for keywords such as "WordPress lazyload plugin" you should be able to find...

If you are satisfied with just the supported functions, it is good, but you can't configure and customize it in detail .



Recommended: Defer.js

deferjs_logo_image

If you plan to  embed social networking services such as Twitter, Instagram, TokTok  , or  source code display libraries such as Prism.js or highlight.js  into your site pages, I recommend Defer.js built-in is recommended: ‼️

The recommendation is so good that I translated the official documentation into Japanese and wrote an article explaining how to use it...



4 optional features of Defer.js


  1. Lazy-Load of almost anything, including not only img / iframe elements, JS and CSS files, but also JS functions
  2. Lazy-Load is possible just before the target element appears on the screen ( timing can be specified )
  3. When lazy-loading the target element, JS (inline) functions are executed for each element
  4. When lazy-loading the target element, CSS classes can be added after lazy-loading ( i.e., CSS effects can be delayed )

Added support for responsive images and <picture> elements .

In addition to its many functions, its ultra-compact implementation, only 1.81 KByte (about 1,810 characters) when embedded inline in a site, is one of its advantages over other "Lazy-Load JS Libraries" .

Pure JavaScript = Vanilla.js
( jQuery not required❗️ )



It seems that the combination of "Lazy-Load" and "resource (preload) hint" is the most effective option in the current web technology .

 In addition to the defer (lazy-load) function, the resource (preload) hint function has been added to the Defer.all() function since Version: 3.2.0❗️ 

The "preload" of the JS-file specified as an argument to the Defer.all() function , is automatically performed .









Famous lazy-load JS Libraries

Defer.js Two JS Libraries for comparison, "lazysizes.js" has been around for about 2 years and "lazyload.js" has not been updated for about 4 years .

Defer.js was released in early 2019, but is updated frequently, with new versions released at least annually . I've also read the introductory articles on "lazysizes.js" and "lazyload.js" , and the author of Defer.js seems to have done a lot of research on them, and they're feature-wise the strongest❗️

The relatively new "lazysizes.js" can specify the timing of loading by pixels, while Defer.js and "lazyload.js" can specify the Intersection Observer API options as is .

In "lazysizes.js" , the unveilhooks plugin is not necessary if the background image is lazy-loaded with CSS, but this is also equivalent or better, as shown in the Defer.js "Add any CSS class to the target element after lazy load" sample .


The first argument of the lazyload() function for executing the "lazyload.js" library is an element array (node list), and the second argument is options of the Intersection Observer API .

The Defer.dom() function of the Defer.js library is an improved version of this function .







The following article provides an easy-to-understand explanation of the Intersection Observer API's options .

The rootMargin can be specified as  "800px 0px or  "100% 0% like CSS margin .

(  2023/05/23  Fixed a problem with rootMargin using px for absolute and % for relative, which could cause problems if not specified as  0px  or  0%  in the Chrome browser . )





 Thank you for reading to the end.


Previous Post
No Comment
Add Comment
comment url