Search code examples
javascripthtmlcsspageload

How to implement a page loader animation only for webpages that take more than a certain amount of time to load?


I've got a page loader animation currently working successfully by calling window.onload() in my JavaScript, but I'd like to tweak the code so that the loader animation only triggers if the webpage takes more than a certain amount of time to load. I'm attempting to avoid having the animation display every time that the user navigates to a new page, and only when it's necessary.

Below is my current HTML, CSS, and JS code, if it's helpful.

HTML:

<div class="loader">
        <img class="loading-gif" src="./assets/img/loading.gif" alt="Page Loading...">
</div>

CSS:

.loader {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 1001;
    width: 100%;
    height: 100%;
    background: var(--bg-color);
    display: flex;
    justify-content: center;
    align-items: center;
}

.loading-gif {
    width: 100px;
}

.loader.fade-out {
    animation: fadeOut var(--speed);
    animation-fill-mode: forwards;
}

@keyframes fadeOut {
    100% {
        opacity: 0;
        visibility: hidden;
    }
}

JavaScript:

window.onload = function() {
    const loader = document.querySelector(".loader")
    loader.classList.add("fade-out")
}

Thank you so much for any help that you can provide!


Solution

  • In a word, this isn't possible. To achieve this effect you would need to know in advance the rate at which the client will download your webpage and the assets required for the webpage's initial render. You can't know, or even reliably predict, the client's download rate over time because the variables that affect network conditions are too complex. For example, the end user may enter a tunnel while downloading your webpage causing a sudden and unpredictable decrease in available download bandwidth, or other applications on the end user's device may make network requests that compete with the download in progress for bandwidth.

    The best you can do to approximate this effect would be to use the onprogress event of XMLHttpRequest to determine the current download rate and the size of the asset being transferred to calculate when the asset will finish downloading, ASSUMING the download rate remains the same.

    Here's a snippet you could use to figure out how to approximate the effect.

    const xhr = new XMLHttpRequest();
    xhr.open('GET', '/myasset.json}', true);
    
    xhr.onprogress = e => {
        if (e.lengthComputable) {
            const percentComplete = (e.loaded / e.total) * 100;
            console.log(percentComplete, 'percentComplete');
        }
    }
    
    xhr.onload = function() {
            console.log("loaded");
    }
    
    xhr.send();