Back

Creating a Dynamic Circular Progress Animation

Learn how to build an elegant loader with rotating concentric rings that visually communicate progress using CSS animations.

HTML

The HTML structure for our circular progress loader is elegantly minimal. We have a main container with the class "circular-loader" that contains three nested div elements, each with the class "ring" and an additional class to specify its position ("outer-ring", "middle-ring", and "inner-ring").
        <div class="circular-loader">
          <div class="ring outer-ring"></div>
          <div class="ring middle-ring"></div>
          <div class="ring inner-ring"></div>
        </div>
      

CSS

Let's start by setting up our loader container. We create a relative-positioned container with specific dimensions to house our rings. We use flexbox to center its contents both horizontally and vertically.
        .circular-loader {
            position: relative;
            width: 80px;
            height: 80px;
            display: flex;
            justify-content: center;
            align-items: center;
        }
      
Next, we define the common properties for all rings. Each ring is a circular element created using border-radius: 50%. We set most of the border to be transparent, with only specific segments colored to create a partial circle effect. All rings will share the same rotate animation, though with different durations as we'll see shortly.
        .ring {
            position: absolute;
            border-radius: 50%;
            border: 3px solid transparent;
            animation: rotate 3s linear infinite;
        }
      
Now we style each ring individually, defining their sizes and which border segments are colored. We use a gradient of blue shades from dark blue for the outer ring to light blue for the inner ring. The outer ring is the largest at 70px by 70px with its top and left borders colored blue. The animation duration is set to 3.5 seconds.
        .outer-ring {
            width: 70px;
            height: 70px;
            border-top-color: #3B82F6;
            border-left-color: #3B82F6;
            animation-duration: 3.5s;
        }
      
The middle ring is 50px by 50px with its right and bottom borders colored in a slightly lighter blue. We set its animation to run in reverse direction compared to the other rings, creating an interesting counterflow effect. The animation completes in 2.5 seconds.
        .middle-ring {
            width: 50px;
            height: 50px;
            border-right-color: #60A5FA;
            border-bottom-color: #60A5FA;
            animation-duration: 2.5s;
            animation-direction: reverse;
        }
      
The inner ring is the smallest at 30px by 30px with its top and right borders colored in the lightest blue shade. This ring completes its rotation in just 1.5 seconds, making it the fastest.
        .inner-ring {
            width: 30px;
            height: 30px;
            border-top-color: #93C5FD;
            border-right-color: #93C5FD;
            animation-duration: 1.5s;
        }
      
The animation is defined using the @keyframes rule. We combine rotation and scaling for a more dynamic effect. Each ring begins at 0 degrees with normal scale, rotates to 180 degrees at the midpoint while growing slightly (scale 1.1), and completes a full 360-degree rotation while returning to its original size.
        @keyframes rotate {
            0% {
                transform: rotate(0) scale(1);
            }
            50% {
                transform: rotate(180deg) scale(1.1);
            }
            100% {
                transform: rotate(360deg) scale(1);
            }
        }
      
The combination of different sizes, colors, rotation directions, and speeds creates a mesmerizing and complex animation despite the relatively simple code. The rings appear to be in constant motion while maintaining a harmonious relationship to each other. The subtle scaling effect adds depth to the animation, making the rings appear to pulse slightly as they rotate, enhancing the sense of activity. This circular progress loader offers several unique advantages: - Continuous feedback: The constant motion clearly communicates that a process is ongoing without indicating a specific percentage of completion. - Visual depth: The concentric rings with different colors and motion patterns create a sense of depth and dimension that's visually interesting. - Professional aesthetic: The blue color scheme and smooth animations project a polished, professional look appropriate for business applications, dashboards, or data-processing interfaces. - Space efficiency: The circular design makes efficient use of space while still providing clear visual feedback. - Customization potential: By adjusting colors, sizes, border widths, and animation timings, this loader can be adapted to match a wide range of design languages. The circular progress loader's elegant, perpetual motion communicates an active state while adding visual interest to the user interface during wait times.

Whole code

<div class="circular-loader">
  <div class="ring outer-ring"></div>
  <div class="ring middle-ring"></div>
  <div class="ring inner-ring"></div>
</div>

<style>
.circular-loader {
  position: relative;
  width: 80px;
  height: 80px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.ring {
  position: absolute;
  border-radius: 50%;
  border: 3px solid transparent;
  animation: rotate 3s linear infinite;
}

.outer-ring {
  width: 70px;
  height: 70px;
  border-top-color: #3B82F6;
  border-left-color: #3B82F6;
  animation-duration: 3.5s;
}

.middle-ring {
  width: 50px;
  height: 50px;
  border-right-color: #60A5FA;
  border-bottom-color: #60A5FA;
  animation-duration: 2.5s;
  animation-direction: reverse;
}

.inner-ring {
  width: 30px;
  height: 30px;
  border-top-color: #93C5FD;
  border-right-color: #93C5FD;
  animation-duration: 1.5s;
}

@keyframes rotate {
  0% {
    transform: rotate(0) scale(1);
  }
  50% {
    transform: rotate(180deg) scale(1.1);
  }
  100% {
    transform: rotate(360deg) scale(1);
  }
}
</style>
      
Thank you for reading this article.

Comments

No comments yet. Be the first to comment!

More loaders

Similar

See also