Paulund

CSS Loading Spinners

We all know that CSS3 brings a lot of features which allows you to do a lot of cool stuff that we used to need Javascript for. One of the features that we're going to look at today is creating loading spinners with just CSS and show the variety of spinners we can create. In the past we had to create the spinners with Javascript to do the animation for you, but now with CSS we can do this without the need of any Javascript. In this tutorial we're going to create 8 different loading spinners using just CSS. View the demo to see these spinners in action.

Loading Bars

The loading bars spinner is probably the most common loading spinner you will see, it is made up of 8 lines which spin together in a circle, each of the lines will have different opacity. The spinning effect will come from changing the opacity of each of the loading bars, making it look like the entire thing is spinning.

The HTML

First we start off by creating the HTML for the spinner, all you have to do create a parent element with 8 child elements.

<div class="loading bar">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</div>

The CSS

The CSS starts out by creating the look of the spinner, this means we need to style the parent item to have enough space for all the child bars. Each of the child elements will be styled as bars but with different opacity, we do this by using the nth-child to pick which element to style. We start off by styling the parent element which we will make a box 100 pixels by 100 pixels.

.loading{
    width:100px;
    height:100px;
    margin:30px auto;
    position:relative;
}

Next we will style each of the bars, for these we are simply creating lines of width 10px and height of 30px, then we will set a background colour of black. This is where we will set the CSS animation of fadeit to all bars, this animation will simply change the opacity from full to blank.

.loading.bar div{
    width: 10px;
    height: 30px;
    background: black;
    position: absolute;
    top: 35px;
    left: 45px;
    opacity:0.05;

    -webkit-animation: fadeit 1.1s linear infinite;
    animation: fadeit 1.1s linear infinite;
}

Once the bars have been styled we can now place these in a circle by using transform rotate and the translate functions. This is done by using the nth-child to pick each bar and position them separately.

.loading.bar div:nth-child(1){
    -webkit-transform: rotate(0deg) translate(0, -30px);
    transform: rotate(0deg) translate(0, -30px);

    -webkit-animation-delay:0.39s;
    animation-delay:0.39s;
}
.loading.bar div:nth-child(2){
    -webkit-transform: rotate(45deg) translate(0, -30px);
    transform: rotate(45deg) translate(0, -30px);

    -webkit-animation-delay:0.52s;
    animation-delay:0.52s;
}
.loading.bar div:nth-child(3){
    -webkit-transform: rotate(90deg) translate(0, -30px);
    transform: rotate(90deg) translate(0, -30px);

    -webkit-animation-delay:0.65s;
    animation-delay:0.65s;
}
.loading.bar div:nth-child(4){
    -webkit-transform: rotate(135deg) translate(0, -30px);
    transform: rotate(135deg) translate(0, -30px);

    -webkit-animation-delay:0.78s;
    animation-delay:0.78s;
}
.loading.bar div:nth-child(5){
    -webkit-transform: rotate(180deg) translate(0, -30px);
    transform: rotate(180deg) translate(0, -30px);

    -webkit-animation-delay:0.91s;
    animation-delay:0.91s;
}
.loading.bar div:nth-child(6){
    -webkit-transform: rotate(225deg) translate(0, -30px);
    transform: rotate(225deg) translate(0, -30px);

    -webkit-animation-delay:1.04s;
    animation-delay:1.04s;
}
.loading.bar div:nth-child(7){
    -webkit-transform: rotate(270deg) translate(0, -30px);
    transform: rotate(270deg) translate(0, -30px);

    -webkit-animation-delay:1.17s;
    animation-delay:1.17s;
}
.loading.bar div:nth-child(8){
    -webkit-transform: rotate(315deg) translate(0, -30px);
    transform: rotate(315deg) translate(0, -30px);

    -webkit-animation-delay:1.3s;
    animation-delay:1.3s;
}

The animation for these bars is named fadeit, which simply changes the opacity from full to blank.

@-webkit-keyframes fadeit{
    0%{ opacity:1; }
    100%{ opacity:0;}
}
@keyframes fadeit{
    0%{ opacity:1; }
    100%{ opacity:0;}
}

Bar Spinner

The bar spinner is similar to the loading bar spinner, but the difference is that instead of changing the opacity of each of the bars we are going to spin the entire parent element so we can see the difference between the first two spinners.

The HTML

The HTML for the bar spinner is exactly the same as the first spinner we have a parent element with 8 child elements.

<div class="spinner bar">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</div>

The CSS

The styling of these bars are going to be exactly the same as the first spinner, the only difference between them is that the animation will rotate the entire spinner and will not change the individual bars opacity. Again we start off by styling the outer parent element, by creating a square box of 100px width and 100px height.

.spinner{
    width:100px;
    height:100px;
    margin:30px auto;
    position:relative;
    -webkit-animation: rotateit 1.3s linear infinite;
    animation: rotateit 1.3s linear infinite;
}

Notice the animation of this element is set to rotateit this animation will be used to rotate the element 360 degrees, because this is set to infinite the spinner will continue to rotate.

@-webkit-keyframes rotateit {
  from { -webkit-transform: rotate(360deg); }
  to { -webkit-transform: rotate(0deg); }
}
@keyframes rotateit {
  from { transform: rotate(360deg); }
  to { transform: rotate(0deg); }
}

This will make sure that the parent element will rotate 360 degrees, now we can just style the bars inside the parent element. This will be exactly the same as the first example, except we don't need to add the animation delay.

.spinner.bar div{
    width: 10px;
    height: 30px;
    background: black;
    position: absolute;
    top: 35px;
    left: 45px;
}
.spinner.bar div:nth-child(1){
    -webkit-transform: rotate(0deg) translate(0, -30px);
    transform: rotate(0deg) translate(0, -30px);
}
.spinner.bar div:nth-child(2){
    -webkit-transform: rotate(45deg) translate(0, -30px);
    transform: rotate(45deg) translate(0, -30px);
    opacity:0.7;
}
.spinner.bar div:nth-child(3){
    -webkit-transform: rotate(90deg) translate(0, -30px);
    transform: rotate(90deg) translate(0, -30px);
    opacity:0.6;
}
.spinner.bar div:nth-child(4){
    -webkit-transform: rotate(135deg) translate(0, -30px);
    transform: rotate(135deg) translate(0, -30px);
    opacity:0.5;
}
.spinner.bar div:nth-child(5){
    -webkit-transform: rotate(180deg) translate(0, -30px);
    transform: rotate(180deg) translate(0, -30px);
    opacity:0.4;
}
.spinner.bar div:nth-child(6){
    -webkit-transform: rotate(225deg) translate(0, -30px);
    transform: rotate(225deg) translate(0, -30px);
    opacity:0.3;
}
.spinner.bar div:nth-child(7){
    -webkit-transform: rotate(270deg) translate(0, -30px);
    transform: rotate(270deg) translate(0, -30px);
    opacity:0.2;
}
.spinner.bar div:nth-child(8){
    -webkit-transform: rotate(315deg) translate(0, -30px);
    transform: rotate(315deg) translate(0, -30px);
    opacity:0.1;
}

Circle Spinner

The circle spinner is a spinner that is similar to the bar spinner except we are using circles instead of bars, this is easily done with CSS by using the border-radius property and applying a value of 50% to make the elements rounded.

The HTML

The circle spinner HTML is exactly the same as the first 2 examples, it has a parent element with 8 child elements inside it. All the work for customising the spinner is done with CSS.

<div class="spinner circles">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</div>

The CSS

The parent element of the circle spinner will be styled the same as the bar spinner, it is a 100 x 100 pixel box which has a animation of rotate will spin the parent element 360 degrees.

.spinner{
    width:100px;
    height:100px;
    margin:30px auto;
    position:relative;
    -webkit-animation: rotateit 1.3s linear infinite;
    animation: rotateit 1.3s linear infinite;
}

@-webkit-keyframes rotateit { from { -webkit-transform: rotate(360deg); } to { -webkit-transform: rotate(0deg); } } @keyframes rotateit { from { transform: rotate(360deg); } to { transform: rotate(0deg); } }

The difference between the bar spinner and the circle spinner is the way we style the child elements with the circles being all the same sizes.

.spinner.circles div{
    width: 20px;
    height: 20px;
    border-radius:50%;
    background: black;
    position: absolute;
    top: 35px;
    left: 45px;
}

The next styles for the circles are going to be exactly the same as the bar spinners except for one difference, the scale of the circle. Using the transform scale property we can change the size of the circles to make them smaller around the spinner.

.spinner.circles div:nth-child(1){
    -webkit-transform: rotate(0deg) translate(0, -35px) scale(1.4);
    transform: rotate(0deg) translate(0, -35px) scale(1.4);
}
.spinner.circles div:nth-child(2){
    -webkit-transform: rotate(45deg) translate(0, -35px) scale(1.2);
    transform: rotate(45deg) translate(0, -35px) scale(1.2);
    opacity:0.7;
}
.spinner.circles div:nth-child(3){
    -webkit-transform: rotate(90deg) translate(0, -35px) scale(1.1);
    transform: rotate(90deg) translate(0, -35px) scale(1.1);
    opacity:0.6;
}
.spinner.circles div:nth-child(4){
    -webkit-transform: rotate(135deg) translate(0, -35px) scale(0.9);
    transform: rotate(135deg) translate(0, -35px) scale(0.9);
    opacity:0.5;
}
.spinner.circles div:nth-child(5){
    -webkit-transform: rotate(180deg) translate(0, -35px) scale(0.7);
    transform: rotate(180deg) translate(0, -35px) scale(0.7);
    opacity:0.4;
}
.spinner.circles div:nth-child(6){
    -webkit-transform: rotate(225deg) translate(0, -35px) scale(0.5);
    transform: rotate(225deg) translate(0, -35px) scale(0.5);
    opacity:0.3;
}
.spinner.circles div:nth-child(7){
    -webkit-transform: rotate(270deg) translate(0, -35px) scale(0.3);
    transform: rotate(270deg) translate(0, -35px) scale(0.3);
    opacity:0.2;
}
.spinner.circles div:nth-child(8){
    -webkit-transform: rotate(315deg) translate(0, -35px) scale(0.1);
    transform: rotate(315deg) translate(0, -35px) scale(0.1);
    opacity:0.1;
}

Facebook Loader

If your a user of Facebook then you most likely have seen the Facebook loader, which is made up of 3 bars which grow from left to right.

The HTML

The HTML for the Facebook loader is very simple it has a parent element with 3 elements inside. The child elements will be used as the 3 bars that will grow as part of the animation.

<div class="facebook">
    <div></div>
    <div></div>
    <div></div>
</div>

The CSS

For the CSS we are going to simply style each of the bars exactly the same, as 3 blue bars. On each of the bars we are going to add the CSS animation, all the animation will do is scale the element and change the opacity of bar. This will fade out the bars and grow them at the sametime.

.facebook div{
    height:50px;
    width:20px;
    display:inline-block;
    background-color: #56bbdb;
    border:1px solid #217c99;

    -webkit-animation:facebook_loader 1.3s linear infinite;
    animation:facebook_loader 1.3s linear infinite;

    -webkit-transform: scale(0.91);
    transform: scale(0.91);
}

For each of the bars we are going to change the animation delay to make the animation run at different times, this makes the bars load in a wave.

.facebook div:nth-child(1){
    -webkit-animation-delay:0.39s;
    animation-delay:0.39s;
}
.facebook div:nth-child(2){
    -webkit-animation-delay:0.52s;
    animation-delay:0.52s;
}
.facebook div:nth-child(3){
    -webkit-animation-delay:0.65s;
    animation-delay:0.65s;
}

Next we can create the CSS animation, all we are doing is changing the scale and the opacity of the element.

@-webkit-keyframes facebook_loader{
    0%{
        -webkit-transform:scale(1.2);
        opacity:1
    }

    100%{
        -webkit-transform:scale(0.7);
        opacity:0.1
    }
}

@keyframes facebook_loader{
    0%{
        transform:scale(1.2);
        opacity:1
    }

    100%{
        transform:scale(0.7);
        opacity:0.1
    }
}

SpinKit

The following spinners can be found on the github project SpinKit. SpinKit

Spinning Square

The spinning square animation will simply take a square and rotate it vertically and then horizontally.

The HTML

As this is just one element the HTML is going to be just one div.

<div class="spinning-square"></div>

The CSS

First the CSS is used to style the square then we can add the animation to spin the square. The square is simply going to be a black square of 60 x 60 pixels, then add the CSS animation of rotatesquare.

 .spinning-square {
    width: 60px;
    height: 60px;
    background-color: #333;

    margin: 0 auto;
    -webkit-animation: rotatesquare 1.2s infinite ease-in-out;
    animation: rotatesquare 1.2s infinite ease-in-out;
}

The CSS animation rotatesquare will take the CSS perspective function to change the position of the element from the z-index, this will allow us to rotate the element on the Y-axis to flip it vertically. Then we can use the rotateX function to rotate the element on the X-axis.

@-webkit-keyframes rotatesquare {
    0% { -webkit-transform: perspective(120px) }
    50% { -webkit-transform: perspective(120px) rotateY(180deg) }
    100% { -webkit-transform: perspective(120px) rotateY(180deg)  rotateX(180deg) }
}

@keyframes rotatesquare {
  0% { transform: perspective(120px) rotateX(0deg) rotateY(0deg); } 
  50% { transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg); } 
  100% { transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); }
}

Spinner Bounce Circle

The spinner bounce circle will take 2 circles and bounce them inside each other.

The HTML

The HTML for this spinner is a parent element with 2 child elements inside, these child elements will be used for the bouncing circles.

<div class="spinner-bounce-circle">
    <div></div>
    <div></div>
</div>

The CSS

The parent element will be styled as an area to add the circles in, we just need to add a width and height to the area.

.spinner-bounce-circle
{
    width: 60px;
    height: 60px;

    position: relative;
    margin: 0 auto;
}

Then we can style each of the circles, this will mean adding a size of 100% to the element, adding a border-raduis of 50% will make the element rounded. Then we can add a background colour to the circle with an opacity of 0.6. Here is where we add the CSS animation of circlebounce which is used to change the scale of the element from nothing to full. As the scale of the element will need to happen at different times we are going to add an animation-delay to the first element.

.spinner-bounce-circle div
{
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background-color: #333;
    opacity: 0.6;
    position: absolute;
    top: 0;
    left: 0;

    -webkit-animation: circlebounce 2.0s infinite ease-in-out;
    animation: circlebounce 2.0s infinite ease-in-out;
}

.spinner-bounce-circle div:nth-child(1) {
    -webkit-animation-delay: -1.0s;
    animation-delay: -1.0s;
}

The CSS circlebounce animation will simply change the scale of the element from nothing to full sized.

@-webkit-keyframes circlebounce {
    0%, 100% { -webkit-transform: scale(0.0) }
    50% { -webkit-transform: scale(1.0) }
}

@keyframes circlebounce {
    0%, 100% { transform: scale(0.0); }
    50% { transform: scale(1.0); }
}

Wave Loader

The wave loader is similar to the facebook loader as it will take a number of bars and change the scale of the elements in a row to make a wave effect.

The HTML

The HTML is made up of one parent element with five child elements inside it, the child elements are going to be used as the bars for the wave.

<div class="spinner-wave">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</div>

The CSS

The CSS of the wave will start by setting up a box area of the bars to be included, this is simply a 100 x 100 box.

.spinner-wave {
    margin: 0 auto;
    width: 100px;
    height: 50px;
    text-align: center;
}

Next we can style the child elements, these will be 5 bars with a black background and a wave animation added to all the elements. As we need these elements to run at different times then we can set the delay of the elements to be different times. We do this by using the nth-child selector with the animation-delay to pick different delays for each element.

.spinner-wave > div {
    background-color: #333;
    height: 100%;
    width: 6px;
    display: inline-block;

    -webkit-animation: wave 1.2s infinite ease-in-out;
    animation: wave 1.2s infinite ease-in-out;
}

.spinner-wave div:nth-child(2) {
    -webkit-animation-delay: -1.1s;
    animation-delay: -1.1s;
}

.spinner-wave div:nth-child(3) {
    -webkit-animation-delay: -1.0s;
    animation-delay: -1.0s;
}

.spinner-wave div:nth-child(4) {
    -webkit-animation-delay: -0.9s;
    animation-delay: -0.9s;
}

.spinner-wave div:nth-child(5) {
    -webkit-animation-delay: -0.8s;
    animation-delay: -0.8s;
}

The wave animation is going to be similar to the bounce circle animation it will simply scale the element from small to large, with each of the elements starting at different times it will create the wave effect.

@-webkit-keyframes wave {
    0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
    20% { -webkit-transform: scaleY(1.0) }
}

@keyframes wave {
    0%, 40%, 100% { transform: scaleY(0.4); }
    20% { transform: scaleY(1.0); }
}

Rotating Cubes

The rotating cubes loader will take two cubes and spin them around each other in a small circle, they will grow and shrink depending on position of the cubes.

The HTML

The HTML for the cubes is very simple you just need a parent element and two child elements, these child elements will be used to style the cubes for the spinner.

<div class="spinner-cube">
    <div></div>
    <div></div>
</div>

The CSS

The styling of the parent element will create an area of 60 x 60 pixels for the cubes to stay within.

.spinner-cube
{
    margin: 0 auto;
    width: 60px;
    height: 60px;
    position: relative;
}

The child elements will need to be styled the same as each other, they have a black background and a width and height of 20 x 20 pixels. Next will be the CSS animation of cuberotate which will run on both elements. We want to start the cubes animation at different times so it creates the effect of spinning around each other.

.spinner-cube > div
{
    background-color: #333;
    width: 20px;
    height: 20px;
    position: absolute;
    top: 0;
    left: 0;

    -webkit-animation: cuberotate 1.8s infinite ease-in-out;
    animation: cuberotate 1.8s infinite ease-in-out;
}

.spinner-cube div:nth-child(2)
{
    -webkit-animation-delay: -0.9s;
    animation-delay: -0.9s;
}

Next we can add the cuberotate CSS animation which will be used to move the elements, rotate them and change the scale of each of the elements.

@-webkit-keyframes cuberotate {
    25% { -webkit-transform: translateX(22px) rotate(-90deg) scale(0.5) }
    50% { -webkit-transform: translateX(22px) translateY(22px) rotate(-180deg) }
    75% { -webkit-transform: translateX(0px) translateY(22px) rotate(-270deg) scale(0.5) }
    100% { -webkit-transform: rotate(-360deg) }
}

@keyframes cuberotate {
    25% { transform: translateX(42px) rotate(-90deg) scale(0.5); } 
    50% { transform: translateX(42px) translateY(42px) rotate(-179deg); } 
    50.1% { transform: translateX(42px) translateY(42px) rotate(-180deg); } 
    75% { transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0.5); } 
    100% { transform: rotate(-360deg); }
}

If you want to see these spinners in action just click the link below to view the demo.