/ lazy-load

Lazy Load iFrames

Since 02-March-2019 I am mainting this blog post "Track of the Day", which as you have guessed, I post 1 track every day. At first this was no big deal, however today I reached 67 youtube/soundcloud iFrames and believe me, the page was not happy to load. (can I throw some blame to youtube embed also? yes)

The Fix

I decided if this page was to ever be used or seen by another person I had to speed the page load. There are ways to pre-load the needed files for a youtube embed but that would lead us in a road in which I would have to maintain the code.

The magic solution is also the lazy one 😁

Lazy Load

Lazy loading images or videos is a common practise to improve the page load of a webpage and although Chrome will eventually support it by default (arguably they do it for better marketing analytics.. 🤐), there are also many libraries that help you do that and also handle appropriate color placeholders.
But these are too fancy.

There is one kid on the block called IntersectionObserver. This bad boy literally does what we would have to do with custom listeners to try and understand if an image/video/iframe is currently visible to the user.

It is not yet supported by all browsers but I do not really bother with IE 11..

How-to

The InsersectionObserver has a quite broad API however we will need 3 actions.
Register a IntersectionObserver, observe and unobserve an element.

Bellow is the full code sample, thankfully Ghost allows custom script injection.

document.addEventListener("DOMContentLoaded", function () {
    if ("IntersectionObserver" in window) {
        lazyVids = document.querySelectorAll("iframe");
        var vidObserver = new IntersectionObserver(function (entries, observer) {
            entries.forEach(function (entry) {
                if (entry.isIntersecting && entry.target.src.length == 0) {                    
                    entry.target.src = entry.target.dataset.src;
                    vidObserver.unobserve(entry.target);
                }
            });
        });

        lazyVids.forEach(function (vid) {
            vidObserver.observe(vid);
        });
    // if the IntersectionObserver is not available just load all.. sorry
    } else {
        var lazyVids = document.getElementsByTagName('iframe');

        for (var i = 0; i < lazyVids.length; i++) {
            if (lazyVids[i].getAttribute('data-src')) {
                lazyVids[i].setAttribute('src', lazyVids[i].getAttribute('data-src'));
            }
        }
    }
})

But how does it work?

The key here is that we do not actually set the src= from the start, but we place the actual src in a data attribute like this data-src=http://yoururl.com

In this way, the iframe will not try to load anything on first page load.

However using the script above, we essentially assign the data-src to the src when the element comes into view.

Instead of however having to do it on our own, we assign an observer to listen to those elements and execute an action when they appear in view and then just stop listening (or observing) that element in the future.

Pretty simple but really usefull. Check it out in action here