GitHub 22★

Loading spinner

Spinner lets users know that a particular task is being processed.



A spinner needs only a single element:

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

Before diving into the animation, imagine that the spinner has the same width and height:

.loading-spinner {
height: 4rem;
width: 4rem;

At that moment, it looks like a square. The top side should have a different color:

.loading-spinner {
border: 4px solid #d1d5db;
border-top-color: #3b82f6;

It's the right time to turn its shape into a circle by using the border-radius property. The top side then becomes one of four curves:

.loading-spinner {
border-radius: 50%;


To make the curve move continuously, we will rotate it around itself:

@keyframes spinner {
from {
transform: rotate(0deg);
to {
transform: rotate(360deg);

The final step is to use the animation an infinite number of times:

.loading-spinner {
animation: spinner 800ms linear infinite;

Using SVG circles

There is another approach that is more complex using SVG circle elements. Let's start with constructing the spinner with two circles:

<svg class="svg-spinner">
<!-- The track circle -->
<circle class="svg-spinner__track"></circle>

<!-- The progress circle -->
<circle class="svg-spinner__progress"></circle>

The diameters of both circles are the same as the spinner's size:

stroke-width: 4px;

/* Assume that the spinner has the size of 64px */
cx: 32;
cy: 32;
r: 32;

Rather than covering the full round of spinner, the progress circle only covers a quarter corner. Using the dasharray and dashoffset properties allows us to do that:

.svg-spinner__progress {
/* Math.PI * size */
stroke-dasharray: 201.062;

/* (1 - 0.25) * Math.PI * size */
stroke-dashoffset: 150.796;

I leave the formulations here, so you can calculate the styles dynamically based on the spinner's size.

Using the spinner animation in the previous section gives us the same result:

.svg-spinner {
animation: spinner 800ms linear infinite;

Last but not least, the SVG element must come with a viewBox attribute to indicate the bounding:

<svg class="svg-spinner" viewBox="-2 -2 68 68">...</svg>

The magic numbers -2 -2 68 68 actually is the resulf of the formulation:

-(strokeWidth / 2) -(strokeWidth / 2) (strokeWidth + size) (strokeWidth + size)

The following table describes the variable used in the formulation:

strokeWidthThe border of circles (4)
sizeThe spinner size (64)

See also

Follow me on and to get more useful contents.