I recently noticed that Netlify has the most minimalist loading animation I have ever seen. So, I decided to build it myself and share it with you.
Looking at the loading animation in Netlify website, we can see that it uses 4 characters (|
, /
, -
, and \
) to create the illusion of spinning effect.
That means, we can store the characters in array and repeatedly cycle through each one of them. We also need to find the perfect sweet point for our animation timing and speed create that cool spinning effect.
Ok, let's get started.
First, let's setup the loader in HTML. It's just a div
with an id
of "loader":
<div id="loader"></div>
Now, with CSS, let's center it in the screen and increase the size:
body {
display: grid;
min-height: 100vh;
place-items: center;
margin: 0;
font-size: 5rem;
}
Done. Now onto JavaScript.
First, let's get the loader element from HTML and store it in a variable. We also need to create an array to store the 4 characters for our animation. I'm using letters here to see the animation difference better.
const loader = document.getElementById("loader");
const characters = ["a", "b", "c", "d"];
Now, whenever you need to animate something in JavaScript, you can use this thing called requestAnimationFrame()
. Basically, it tells the browser that we want to perform an animation. I will explain how.
Let's create a function, called animate()
. Inside, we run the requestAnimationFrame()
and pass animate
itself as an argument. And, finally, let's call the animate()
function itself at the end. Because requestAnimationFrame()
runs only once, with this technique we create an infinite loop.
const animate = () => {
requestAnimationFrame(animate);
};
animate();
Right now, nothing seems to be happening. But, animate()
function is continuously running in the background.
Now, to see it, let's create a variable, called frame
, set it to 0, and increment it every time animate()
function runs.
If we console.log
it, we can see the number incrementing. It's quite fast!
let frame = 0;
const animate = () => {
console.log(frame);
frame++;
requestAnimationFrame(animate);
};
animate();
Now, let's update our loader
to show each character as animate()
function runs.
const loader = document.getElementById("loader");
const characters = ["a", "b", "c", "d"];
let frame = 0;
const animate = () => {
loader.innerHTML = characters[frame % 3];
frame++;
requestAnimationFrame(animate);
};
Here, I'm using %
sign (also known as modulo operator) to cycle through the array elements. I'm using 3, since the last index of the array is 3. That way, we always stay within the array.
Looking at the output, it's working but a little too fast.
Do you remember, when we console.log
ed the frame
variable, it was incrementing so fast? Basically, what is happening is that we're changing the loader
character every frame. If, let's say, we manage to update it every 10 frame or 20 frame, it would slow down the animation speed.
const loader = document.getElementById("loader");
const characters = ["a", "b", "c", "d"];
let frame = 0;
const animate = () => {
if (frame % 10 === 0) {
loader.innerHTML = characters[frame % 3];
}
frame++;
requestAnimationFrame(animate);
};
animate();
Now, there'e an issue with our code. Because we're updating every 10 frames (10, 20, 30 and etc), characters[frame % 3]
no longer cycles the array correctly.
So, I found a easier and better approach to solve this.
Let's create a separate variable, called index
that track which character we're showing. And, if the index
gets bigger than our array length, we reset it to 0.
const loader = document.getElementById("loader");
const characters = ["a", "b", "c", "d"];
let frame = 0;
let index = 0;
const animate = () => {
if (frame % 10 === 0) {
if (index >= characters.length) index = 0;
loader.innerHTML = characters[index];
index++;
}
frame++;
requestAnimationFrame(animate);
};
animate();
Now, we can freely chose when to update the content, and not worry about characters not showing up correctly.
Try different frame intervals to control the speed - higher values slow down the animation and lower values speed it up.
Now, if we change the letters back to characters, we get the same result as we saw with Netlify example.
const loader = document.getElementById("loader");
const characters = ["|", "/", "-", "\\"];
let frame = 0;
let index = 0;
const animate = () => {
if (frame % 10 === 0) {
if (index >= characters.length) index = 0;
loader.innerHTML = characters[index];
index++;
}
frame++;
requestAnimationFrame(animate);
};
animate();
And, that's it. Hope you learned something new.
As always, thanks for reading and I'll see you in the next one.
Top comments (5)
fun!
That's the way we used to make (command line) spinners back in the days (some 30 years ago ;)
But maybe you don't need javascript: here is a css only idea for you. Cheers!
And you can still get the jagged looking effect like this using
steps()
Didn't think about that one. I was wondering how to implement it. Thanks :)
New ideas are always appreciated. I'm also thinking of doing it with Sass, perhaps store 4 characters in a map and loop through them. 🤔
Some comments may only be visible to logged-in visitors. Sign in to view all comments.