Introduction
Spinners or loaders are essential elements of modern web design. They offer visual feedback during data fetching, form submissions, or page loads—keeping users engaged while content is being processed. In this tutorial, we’ll build a beautiful dual-themed circular spinner purely with HTML and CSS. It’s sleek, customizable, and requires no JavaScript.

Project Overview
We’ll create two animated circular spinners using reusable HTML and CSS. Each spinner features rotating rings with glowing orbs in the center, giving an illusion of perpetual motion. The second spinner is styled using an alternate theme to show how easily the design can be adapted.
<div class="spinner-box">
<div class="spin-ring ring-one"><span></span></div>
<div class="spin-ring ring-two"><span></span></div>
<div class="spin-ring ring-three"><i></i></div>
<div class="spin-ring ring-four"><i></i></div>
</div>
<div class="spinner-box theme-alt">
<div class="spin-ring ring-one"><span></span></div>
<div class="spin-ring ring-two"><span></span></div>
<div class="spin-ring ring-three"><i></i></div>
<div class="spin-ring ring-four"><i></i></div>
</div>
Each .spinner-box
acts as a container for four spinning elements:
.ring-one
and.ring-two
: Have gradient-filled left halves..ring-three
and.ring-four
: Feature glowing dots using<i>
elements for a futuristic visual.- The second
.spinner-box
uses the classtheme-alt
to apply a different color palette.
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #0a0a0a;
flex-direction: column;
gap: 40px;
}
This centers both spinners vertically and horizontally with a dark background for contrast.
@keyframes spin360 {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
A simple keyframe animation named spin360
that rotates elements in a full circle infinitely.
.spinner-box {
position: relative;
width: 100%;
height: 220px;
display: flex;
align-items: center;
justify-content: center;
-webkit-box-reflect: below 0 linear-gradient(transparent, transparent, rgba(0, 0, 0, 0.2));
}
This creates the base container with a subtle reflection using -webkit-box-reflect
for a modern touch.
.spin-ring {
position: absolute;
width: 200px;
height: 200px;
border-radius: 50%;
animation: spin360 2s linear infinite;
}
Defines the circular rings and applies the spinning animation.
.ring-one:before, .ring-two:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 100%;
background: linear-gradient(to top, transparent, rgba(0, 255, 249, 0.5));
background-size: 100px 180px;
border-top-left-radius: 100px;
border-bottom-left-radius: 100px;
}
Adds a glowing gradient to the left half of the ring for a semi-filled look.
.ring-two, .ring-four {
animation-delay: -1s;
filter: hue-rotate(270deg);
}
Delays animation and shifts hue to add contrast between the rings.
.spin-ring i {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 22px;
height: 22px;
background: #00fff9;
border-radius: 50%;
z-index: 10;
box-shadow: 0 0 10px, 0 0 20px, 0 0 30px, 0 0 40px #00fff9;
}
Creates the glowing dots at the top center of each rotating ring.
.spin-ring span {
position: absolute;
inset: 20px;
background: #0a0a0a;
border-radius: 50%;
z-index: 1;
}
Adds an inner circle to cover the center of the spinner, enhancing its visual depth.
Alternate Theme Styling
.theme-alt .ring-one:before,
.theme-alt .ring-two:before {
background: linear-gradient(to top, transparent, rgba(255, 173, 158, 0.5));
}
Changes the primary glow to a warm peachy color.
.theme-alt .ring-two,
.theme-alt .ring-four {
animation-delay: -1s;
filter: hue-rotate(180deg);
}
Uses a different hue rotation for the alternate set of rings.
.theme-alt .spin-ring i {
background: #ffa59e;
box-shadow: 0 0 10px #ffb0ab, 0 0 20px #ffb0ab, 0 0 30px #ffb0ab, 0 0 40px #ffb0ab;
}
Changes the glowing dot’s color to match the alternate theme.
Final Output
The result is two visually captivating circular loaders that can be reused across websites and apps. They’re responsive, modern, and can be themed with minimal CSS changes.
Conclusion
CSS-powered loaders like this not only enhance the user experience but also demonstrate the power of animations without needing any JavaScript. This spinner setup can be customized with different colors, sizes, and animation speeds—making it a flexible addition to any project.
Add it to your project as a loader while fetching data or during page transitions for a sleek and modern feel. Happy Coding 🙂
Inspired from Michelle L