CSS Funstuff: CSS Spinner
Roland Taylor
Posted on May 1, 2022
Hey all!
Time for a yet another CSS Funstuff tutorial! This time, we'll be creating an animated spinner with pure HTML+CSS! I have to warn you though, this one is a little longer than usual.
After all, it comes with territory, working with CSS.
Let's get right to it!
1st! Setting Up The Basics:
First, as always, let's style the background and set up some defaults. I use the same style in every project in this series, as you probably know by now.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: rgb(35, 35, 35);
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
2nd: Building Our Spinner Object in HTML:
We'll need one div for the inside of the spinner, which ironically, is the container for everything else. What can I say? CSS - it's fascinating.
<div class="spinner">
</div>
We'll set up the CSS later, but for now, let's go ahead and add the divs that will make up the rest of the spinner.
<div class="spinner">
<div class="n-s">
</div>
<div class="w-e">
</div>
<div class="nw-se">
</div>
<div class="sw-ne">
</div>
</div>
You'll notice I've named the classes:
- "n-s"
- "w-e"
- "nw-se"
- "sw-ne"
These names are not chosen at random, and if you have your thinking cap on, you've probably figured out what their names stand for:
- "north->south"
- "west->east"
- "northwest->southeast"
- "southwest->northwest"
Essentially, these are "navigation points" for where we'll be placing the pseudo-elements that make up the rest of our spinner. From this point onward, we'll only be tackling CSS.
The CSS Funstuff!
First let's set up a CSS keyframe animation called spin
. It's always good to keep in mind how things cascade in CSS. It will give our spinner rotation, as well as set the border of the .spinner
class.
@keyframes spin {
0% {
border-color: rgba(255, 0, 0, .735);
transform: rotate(0deg);
}
50% {
border-color: rgba(255, 0, 0, .235);
}
100% {
border-color: rgba(255, 0, 0, .735);
transform: rotate(360deg);
}
}
Next, let's style the .spinner
class.
.spinner {
animation: spin 5s linear 0s infinite normal;
border: 2px solid;
border-radius: 50%;
height: 50px;
position: relative;
width: 50px;
}
We'll set up another animation next, this time called pulse
:
@keyframes pulse {
0% {
opacity: .5;
transform: scale(0);
}
50% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: .5;
transform: scale(0);
}
}
Now you may be wondering, where will this one go? After all, we've already animated the .spinner
class! Well, that's where the pseudo elements come into play:
.spinner::before,
.spinner::after {
border-radius: 50%;
content: '';
inset: 0;
position: absolute;
}
.spinner::after {
animation: pulse 1s linear 0s infinite normal;
border: 1px solid rgba(255, 0, 0, .35);
}
.spinner::before {
animation: pulse .735s linear .235s infinite normal;
border: 5px solid rgba(255, 0, 0, .135);
}
Now, we'll position all the child divs as needed:
.spinner div {
position: absolute;
height: 100%;
width: 100%;
left: 50%;
top: 0;
}
This piece won't be visible, but it's essential.
At this point, you should have something that looks like this:
Following this, we're going to build the rest of the spinner animation. It's a bit of work, so be prepared for reading a lot of code!
Setting up the animation:
As before, we'll tackle the animation first:
@keyframes stretch {
0% {
opacity: 0;
transform: scaleY(0);
}
50% {
opacity: 1;
transform: scaleY(1.5);
}
100% {
opacity: 0;
transform: scaleY(0);
}
}
All the moving parts:
Remember the four classes we added earlier, .n-s
, .w-e
, .sw-ne
, and .nw-se
? Well, the final step is for us to style them:
.spinner div::before,
.spinner div::after {
animation: stretch 2s linear 0s infinite;
animation-fill-mode: both;
background-color: white;
content: '';
height: 15px;
left: -2.5px;
position: absolute;
width: 5px;
z-index: -1;
}
.spinner div:after {
top: -50%;
}
.spinner div::before {
bottom: -50%;
}
.spinner .nw-se,
.spinner .sw-ne,
.spinner .w-e {
left: 0;
}
.spinner .w-e {
top: calc(50% - 2.5px);
transform: rotate(90deg);
}
.spinner .sw-ne {
transform: rotate(45deg);
}
.spinner .nw-se {
transform: rotate(-45deg);
}
.spinner .nw-se::before,
.spinner .nw-se::after,
.spinner .sw-ne::before,
.spinner .sw-ne:after {
left: calc(50% - 2.5px);
left: calc(50% - 2.5px);
}
.spinner .sw-ne:after {
animation-delay: .125s;
}
.spinner .w-e:after {
animation-delay: .25s;
}
.spinner .nw-se:after {
animation-delay: .35s;
}
.spinner .n-s:before {
animation-delay: .5s;
}
.spinner .sw-ne:before {
animation-delay: .65s;
}
.spinner .w-e:before {
animation-delay: .75s;
}
.spinner .nw-se:before {
animation-delay: .85s;
}
The Final Product:
When it's all said and done, this is what you should get:
That's all for now! But wait, there's more! Download the source code. I'll soon update the source with a couple fun tweaks, as I often do in this series, so be on the look out!
[Visit my Gumroad page] for(https://rolandixor.gumroad.com) more like this.
Posted on May 1, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.