Circular loading bar using css only

I've recently started a new project where audio files are played in loops. This presents an interesting challenge as the loading bar makes more sense to be circular rather than linear. Added to this I also wanted to be able to control the amount of time it takes for the animation to complete, and to be able to loop it. Here is how I achieved it!
First up is to create a container which keeps the rotating circles together with the circles inside:

<div class="loader">
    <div class="left"><span></span></div>
    <div class="right"><span></span></div>
</div>

Next is to add some css styling to this container:

.loader {
    display: inline-block;
    position: relative;
}

The display-inline block is to allow the container to be centered on the page, and position relative is to ensure the elements inside are kept together. Next up is the styling for the wrappers:

.left,
.right {
    margin-top: -50px;
    margin-left: -50px;
    position: absolute;
    clip: rect(0, 100px, 100px, 50px);
}

.right {
    clip: rect(0px, 50px, 100px, 0px);
}

Both left and right wrappers are positioned and aligned to their center (half their width). Additionally they are clipped, which hides some of their content. The reason behind this is to make the circles inside half-circles rather than full. Inside the wrappers we can create the circles:

.left span,
.right span {
    width: 80px;
    height: 80px;
    border-radius: 100%;
    position: absolute;
    opacity: 0.7;
    border: 10px solid #fff;
}

This sets the circle sizes and uses border-radius to shape the circles. This method has an extra benefit which means the circles can have opacity, or even an empty space inside like a doughnut. Now all we need are the animations to rotate the circles at the correct times:

.left span {
    clip: rect(0px, 50px, 100px, 0px);
    -webkit-animation: rotate-left 5s infinite linear;
    -moz-animation: rotate-left 5s infinite linear;
    -ms-animation: rotate-left 5s infinite linear;
    -o-animation: rotate-left 5s infinite linear;
    animation: rotate-left 5s infinite linear;
}

.right span {
    clip: rect(0, 100px, 100px, 50px);
    -webkit-animation: rotate-right 5s infinite linear;
    -moz-animation: rotate-right 5s infinite linear;
    -ms-animation: rotate-right 5s infinite linear;
    -o-animation: rotate-right 5s infinite linear;
    animation: rotate-right 5s infinite linear;
}

Each side has a different clipping mask and a different animation to ensure the smooth loop between left and right sides. Finally the actual css animation code:

/* rotate-left */

@-webkit-keyframes rotate-left {
    0% { -webkit-transform: rotate(0deg); }
    50% { -webkit-transform: rotate(180deg); }
    100% { -webkit-transform: rotate(180deg); }
}
@-moz-keyframes rotate-left {
    0% { -moz-transform: rotate(0deg); }
    50% { -moz-transform: rotate(180deg); }
    100% { -moz-transform: rotate(180deg); }
}
@-ms-keyframes rotate-left {
    0% { -ms-transform: rotate(0deg); }
    50% { -ms-transform: rotate(180deg); }
    100% { -ms-transform: rotate(180deg); }
}
@-o-keyframes rotate-left {
    0% { -o-transform: rotate(0deg); }
    50% { -o-transform: rotate(180deg); }
    100% { -o-transform: rotate(180deg); }
}
@keyframes rotate-left {
    0% { transform: rotate(0deg); }
    50% { transform: rotate(180deg); }
    100% { transform: rotate(180deg); }
}

/* rotate-right */

@-webkit-keyframes rotate-right {
    0% { -webkit-transform: rotate(0deg); }
    50% { -webkit-transform: rotate(0deg); }
    100% { -webkit-transform: rotate(180deg); }
}
@-moz-keyframes rotate-right {
    0% { -moz-transform: rotate(0deg); }
    50% { -moz-transform: rotate(0deg); }
    100% { -moz-transform: rotate(180deg); }
}
@-ms-keyframes rotate-right {
    0% { -ms-transform: rotate(0deg); }
    50% { -ms-transform: rotate(0deg); }
    100% { -ms-transform: rotate(180deg); }
}
@-o-keyframes rotate-right {
    0% { -o-transform: rotate(0deg); }
    50% { -o-transform: rotate(0deg); }
    100% { -o-transform: rotate(180deg); }
}
@keyframes rotate-right {
    0% { transform: rotate(0deg); }
    50% { transform: rotate(0deg); }
    100% { transform: rotate(180deg); }
}

And that's it...a working radial animation in Firefox, Chrome, Safari and modern IE browsers. In my demo I've also decided to center the loader vertically and horizontally using table-cells. If you would like to change the animation loop time using JavaScript it's as a simple as using:

circleLeft.style['-webkit-animation-duration'] = '12.5s';
circleRight.style['-webkit-animation-duration'] = '12.5s';

You can view the working version here:

http://jsfiddle.net/kmturley/54hqzmk7/2/

No comments:

Post a Comment