Only CSS loading spinner

Published April 2014

Now that optimizing webpages for retina displays and mobile devices becomes increasingly important, you find tons of webpages offering CSS loading spinners. Unfortunately many of them are quite heavy and require you to add elements to your page in order to create them. I find it most convenient to simply add a class to the element in which I like to show a spinner. Back in the day the class would set an animated GIF as background image. With modern browsers we can achieve this with pure CSS.

The CSS

I like to have things lightweight, here are a few very simple spinners:

@keyframes spinner {
  to {
    transform: rotate(360deg);
  }
}
 
.spinner::before {
  content: "";
  box-sizing: border-box;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 24px;
  margin-top: -12px;
  margin-left: -12px;
  border-radius: 50%;
  border: 2px solid #ccc;
  border-top-color: #000;
  animation: spinner 600ms linear infinite;
}
@keyframes spinner {
  to {
    transform: rotate(360deg);
  }
}
 
.spinner::before {
  content: "";
  box-sizing: border-box;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 32px;
  height: 32px;
  margin-top: -16px;
  margin-left: -16px;
  border-radius: 50%;
  border: 1px solid #ccc;
  border-top-color: #07d;
  animation: spinner 600ms linear infinite;
}
@keyframes spinner {
  to {
    transform: rotate(360deg);
  }
}
 
.spinner::before {
  content: "";
  box-sizing: border-box;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 24px;
  margin-top: -12px;
  margin-left: -12px;
  border-radius: 50%;
  border: 2px solid transparent;
  border-top-color: #07d;
  border-bottom-color: #07d;
  animation: spinner 800ms ease infinite;
}
@keyframes spinner {
  to {
    transform: rotate(360deg);
  }
}
 
.spinner::before {
  content: "";
  box-sizing: border-box;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 24px;
  margin-top: -12px;
  margin-left: -12px;
  border-radius: 50%;
  border-top: 2px solid #07d;
  border-right: 2px solid transparent;
  animation: spinner 600ms linear infinite;
}
@keyframes spinner {
  to {
    transform: rotate(360deg);
  }
}
 
.spinner::before {
  content: "";
  box-sizing: border-box;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 24px;
  margin-top: -12px;
  margin-left: -12px;
  border-radius: 50%;
  border: 1px solid #f6f;
  border-top-color: #0e0;
  border-right-color: #0dd;
  border-bottom-color: #f90;
  animation: spinner 600ms linear infinite;
}

You can play a little with the CSS, there are many ways to customize your spinner. If you want to change the spinning speed for example, reduce the animation duration, e.g. spinner 400ms linear infinite.

Adding your spinner

You can dynamically add the spinner class to any element without needing to include a dedicated spinner element in your HTML:

document.querySelector('.my-spinner').classList.add('spinner');
document.querySelector('.my-spinner').classList.remove('spinner');
 

Instead of only adding the spinner class to elements, you can also use an HTML element which already has the class. Then, give this element an relative or absolute position: .spinner { position: relative; }.

Things to consider

The element you add the spinner class to needs to have an absolute, fixed or relative position. So remember to give it the style position: relative if the element doesn't have an absolute or fixed position.

Also remember that the spinner class occupies the ::before pseudo class. If you rather like to use :after, change the CSS accordingly.

Share Your Thoughts

I’d love to hear your thoughts, questions, or feedback!