If your website contains lots of images, users might see them load onto the page one by one. This is perfectly fine most of the time, but in some cases, you may want all your assets to load before your users see any real content - perhaps to give your users a more cohesive visual experience when they enter your site. To achieve that, we’re going to build this preloader:
For a real-life example, visit my portfolio website and check out its GitHub repo. In case you don’t have time to meticulously sift through unfamiliar code, here are the relevant HTML, SCSS, and JavaScript.
Let’s start with the HTML. Put this block at the top level of your site - you could place it as a direct child of the
<body>
tag, or as a child of whatever element contains your site’s main content.
<div class="preloader">
<div class="preloader__wall preloader__wall--left"></div>
<div class="preloader__wall preloader__wall--right"></div>
<div class="preloader__spinner"></div>
</div>
Now for the fun stuff! This will place the preloader walls side-by-side and make each one cover its half of the window.
.preloader__wall {
background: #2eaee0;
outline: solid 1px #2eaee0; // prevents 1px gap between the walls
position: fixed;
width: 50%;
height: 100%;
transition: transform 0.7s 0.2s;
z-index: 100;
&--left {
left: -50%;
transform: translateX(100%);
}
&--right {
right: -50%;
transform: translateX(-100%);
}
}
Because each wall has width: 50%
and left: -50%
or right: -50%
, they would actually be positioned outside of the
window if it weren’t for their transform
properties. Later, we’re going to set transform: none
to move each wall out
of the window when the rest of your website is done loading.
It might be helpful to read up on the transition and transform properties.
I adapted the spinner from this example. It’s basically a
rotating object with a multicolored border. Try temporarily commenting out the border-radius
to see what I mean.
.preloader__spinner {
border: 6px solid white;
border-top: 6px solid #f57d4e;
border-radius: 50%;
position: fixed;
width: 60px;
height: 60px;
left: 0;
right: 0;
top: 50%;
margin: auto;
z-index: 100;
animation: spin 1.2s linear infinite;
}
@keyframes spin {
0% {
transform: translateY(-50%) rotate(0deg);
}
100% {
transform: translateY(-50%) rotate(360deg);
}
}
It might be helpful to read up on the animation property.
We’re going to add the preloader--finished
class onto the preloader
element with a bit of JavaScript in the next
section. This will move the preloader walls out of the window and hide the spinner.
.preloader--finished {
.preloader__wall {
transform: none;
outline: none;
}
.preloader__spinner {
display: none;
}
}
Now all we have to do is put the preloader into its finished state when the page is done loading. The window’s onload
event fires when all the content on the page (including the DOM, images, scripts, etc.) has loaded, so we’re going to
set a handler function to this event that finds the preloader
element and adds the preloader--finished
class to it.
window.onload = () => {
const preloader = document.getElementsByClassName('preloader')[0];
preloader.classList.add('preloader--finished');
};
You could alternatively use addEventListener
like below. This is useful when you want to add multiple listeners to the
event.
window.addEventListener('load', () => {
const preloader = document.getElementsByClassName('preloader')[0];
preloader.classList.add('preloader--finished');
});
That’s it! Feel free to email or message me if you have any questions or feedback.