Lazy Load Elementor Section with javascript

Viewed 1495

Is there any way to lazy load wordpress elementor section with javascript so that first the page load in a second and then all the section load lazyly o e after another.

1 Answers

I came here, because my section contained one shortcode that would contain some heavy HTML in a sense that it would slow down the page load so massively, due to JavaScript, because these are slick.js sliders and I got three of them on my home page. The slider plugin I'm talking about is Woo Product Slider and Carousel with category.

My idea now was to wrap the short code into my own short code and make sure to trigger the JS to initialize the sliders like so:

[heavy onload="wcpscwc_product_slider_init()"][wcpscwc_pdt_slider cats="133" limit="12"][/heavy]

The heavy shortcode is implemented like this:

/**
 * Heavy
 * 
 * Lazy load heavy elements
 */
add_shortcode('heavy', function ($atts = [], $content = null) {
    if (
        strpos($_SERVER['REQUEST_URI'], '/post.php') !== false ||
        strpos($_SERVER['REQUEST_URI'], 'elementor') !== false
    ) {
        return $content;
    } else {
        $atts = shortcode_atts([
            'offset' => '100',
            'onload' => ''
        ], $atts);

        ob_clean();
        ob_start();

        $id = wp_generate_uuid4();
?>
        <div id="<?php echo $id; ?>" class="heavy-container" data-offset="<?php echo $atts['offset']; ?>" onload="<?php echo $atts['onload']; ?>"></div>
        <script type='text/javascript'>
            (function() {
                window.heavy = window.heavy || {};
                window.heavy["<?php echo $id; ?>"] = <?php echo json_encode(do_shortcode($content)); ?>;
            })();
        </script>
<?php
        return ob_get_clean();
    }
});

It simply stores the HTML encoded in the global heavy object, ready to be initialized once you scroll its corresponding div into the view by using this JS at the bottom of the page (make sure it's executed at the very last moment possible):

(function () {
  window.heavy = window.heavy || {};
  var heavyContainers = document.querySelectorAll(".heavy-container");
  var attemptInitHeavyElements = function () {
    var heavyContainersToLoad = [];
    heavyContainers.forEach(function (container) {
      if (
        window.heavy[container.id] &&
        container.getBoundingClientRect().top - container.dataset.offset <
          window.innerHeight
      ) {
        heavyContainersToLoad.push(container);
      }
    });
    if (heavyContainersToLoad.length) {
      heavyContainersToLoad.forEach(function (container) {
        container.innerHTML = window.heavy[container.id];
        container.onload && container.onload();
        delete window.heavy[container.id];
        container.classList.add("heavy-container--loaded");
      });
    }
  }
  document.addEventListener("scroll", attemptInitHeavyElements);
  attemptInitHeavyElements();
})();

Yes, this solution will not work for sections, but it should work for any content you can encapsulate within a shortcode. It's not very beautiful and can interfere with other lazy load plugins, but it's functional and even works with W3Cache.

This will surely not work with any content, you have to work out the required steps and put them into the onload event of the shortcode, but I hope it will help anybody nonetheless.

Related