CSS Funstuff: CSS Spinner
Published: 2022-05-01 03:23:31

**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.

```css
* {
  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.

```HTML
<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.

```HTML
<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.

```css
@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.

```css
.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`:

```css
@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:

```css
.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:

```css

.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:

{% embed https://youtu.be/DSPOT0jLzY0 %}

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:

```css
@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:

```css
.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:

{% embed https://youtu.be/u9H3DpvEiXQ %}

That's all for now! But wait, there's more! [Download the source code](https://rolandixor.gumroad.com/l/eoilf). 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.