Welcome to a quick tutorial on how to show a loading spinner until the page is fully loaded. This is a seemingly easy thing to do until you get your hands dirty… Some other tutorials online got me to facepalm with their “solution” involving the use of third-party libraries.
No, we don’t need to load an entire library to show a “now loading” screen. In actual fact, it only involves dealing with the loading order of your scripts – Read on for the examples!
ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.
TABLE OF CONTENTS
DOWNLOAD & NOTES
Firstly, here is the download link to the example code as promised.
QUICK NOTES
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.
EXAMPLE CODE DOWNLOAD
Click here to download all the example source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
METHOD 1) LOADING ORDER
All right, let us now get into the first method – Simply reordering your scripts and page structure.
1A) THE HTML
<head>
<!-- (A) LOADING SPINNER -->
<link rel="stylesheet" href="1b-load-spinner.css">
</head>
<body>
<!-- (B) THIS COMES FIRST -->
<div id="loading"></div>
<!-- (C) REST OF THE PAGE -->
<p>YOUR CONTENT HERE</p>
<!-- (D) LOAD JS/CSS LAST -->
<script src="1c-loader.js"></script>
<script>
window.onload = () => {
// JUST DEFINE EMPTY ARRAY [] IF NO CSS/JS TO LOAD
loader(
["my.css"],
["my.js", "https://cdnjs.cloudflare.com/ajax/libs/WHATEVER/"]
);
};
</script>
</body>
Before we get into the script, here’s an important recap – HTML pages load from top to bottom, left to right.
- (A & B) So naturally, we have to prioritize the loading spinner right at the top; The spinner is the first thing that shows while the rest loads.
- (C) Your “regular HTML content” follows after the loading spinner.
- (D) Leave the CSS and Javascript to the end.
1B) FULLSCREEN SPINNER CSS
#loading {
/* (A1) COVER FULL PAGE */
position: fixed;
top: 0; left: 0; z-index: 999;
width: 100vw; height: 100vh;
/* (A2) SPINNER IMAGE */
background-color: black;
background-image: url("ajax-loader.gif");
background-position: center;
background-repeat: no-repeat;
}
Nothing much here. This bit of CSS sets <div id="loading">
to cover the entire screen and adds a loading spinner.
1C) JAVASCRIPT TO LOAD CSS/JS
function loader (css, js) {
// (A) TOTAL NUMBER OF SCRIPTS
var total = css.length + js.length,
now = 0, s;
// (B) READY?
var ready = () => {
now++;
if (now==total) { document.getElementById("loading").remove(); }
};
// (C) INSERT <LINK> INTO <HEAD>
css.forEach((url, i) => {
s = document.createElement("link");
s.rel = "stylesheet";
s.href = url;
s.onload = ready; s.onerror = ready;
document.head.appendChild(s);
});
// (D) INSERT <SCRIPT> INTO <HEAD>
js.forEach((url, i) => {
s = document.createElement("script");
s.src = url;
s.onload = ready; s.onerror = ready;
document.head.appendChild(s);
});
}
Yes, we can just put <script> <link rel="stylesheet"> <style>
at the bottom of the page. But there is also a problem – We cannot track their loading progress without the use of Javascript. Thus this snippet once again, to remove the loading spinner when all the scripts are fully loaded.
METHOD 2) AJAX LOAD
Next, we have an alternative method – Using AJAX to load the page.
2A) THE HTML
<head>
<!-- (A) CSS STYLES -->
<link rel="stylesheet" href="2b-styles.css">
<!-- (B) SCRIPTS -->
<script src="2c-loader.js"></script>
<script>
window.onload = () => { loader("2d-content.html"); };
</script>
</head>
<body>
<!-- (C) HTML PAGE AS USUAL -->
<header>Header</header>
<main id="main"></main>
<footer>Footer</footer>
<!-- (D) LOADING SPINNER -->
<div id="loading"></div>
</body>
Yes, this is more like a “normal HTML page”.
- (A & B) Load the CSS/JS as usual.
- (C) The usual HTML page structure, but take note – The
<main id="main">
section is empty. - (D) The fullscreen loading spinner.
In other words, we load an empty page template first. Then use AJAX to load the content into <main id="main">
. For the uninitiated, this is the principle behind a “one-page app”. The user does not have to reload the entire page, only the content is dynamically refreshed via AJAX.
2B) FULLSCREEN SPINNER CSS
#loading {
/* (A1) COVER FULL PAGE */
position: fixed;
top: 0; left: 0; z-index: 999;
width: 100vw; height: 100vh;
/* (A2) SPINNER IMAGE */
background-color: rgba(0, 0, 0, 0.5);
background-image: url("ajax-loader.gif");
background-position: center;
background-repeat: no-repeat;
/* (A3) HIDDEN BY DEFAULT */
display: none;
}
/* (A4) SHOW LOADING */
#loading.load { display: block; }
Look no further, this is the same. Except that the spinner is hidden by default, we use the .load
to toggle the show/hide.
2C) AJAX LOAD CONTENT
function loader (url, loaded) {
// (A) GET HTML ELEMENTS
var main = document.getElementById("main"),
loading = document.getElementById("loading");
// (B) LOADING SPINNER
loading.classList.add("load");
// (C) AJAX LOAD PAGE
fetch(url)
.then(res => res.text())
.then(txt => {
main.innerHTML = txt;
if (typeof loaded == "function") { loaded(); }
})
.finally(() => {
loading.classList.remove("load");
});
}
Well, we are just using AJAX fetch
to load content into <main>
. Of course, also show the fullscreen loading spinner while it loads.
2D) DUMMY CONTENT
<h1>Hello World</h1>
<p>It works!</p>
Just some dummy content.
USEFUL BITS & LINKS
That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.
LOADING SCREENS ARE NOT GOOD
Loading screens are cool, that’s what I thought as a newbie as well. But in this age of “I want information fast” (how many of you guys actually read everything without “TLDR”), people don’t have much patience to stare at a loading screen.
So spend more effort simplifying your site, not inflating it with all the bells and whistles. It’s counterproductive these days; If you can serve a simple page in 3 seconds, please do so. Leave the loading screen to “complex web apps”.
COMPATIBILITY CHECKS
- Arrow Functions – CanIUse
- Fetch – CanIUse
The examples work on all modern “Grade A” browsers.
LINKS & REFERENCES
- Fullscreen Loading Spinner – Code Boxx
- Fetch – MDN
- Tips for authoring fast-loading HTML pages – MDN
THE END
Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!