25 CSS Spinners17 / 25
Glassmorphism Loader Spinner
A frosted-glass circle with backdrop-filter blur floats over animated colour blobs, with two nested arcs spinning at different speeds to create a layered glassmorphic loading indicator.
Published
This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.
The code
<div class="sp-17">
<div class="sp-17__blobs">
<div class="sp-17__blob"></div>
<div class="sp-17__blob"></div>
<div class="sp-17__blob"></div>
</div>
<div class="sp-17__glass">
<div class="sp-17__arc"></div>
<div class="sp-17__arc-inner"></div>
</div>
</div><div class="sp-17">
<div class="sp-17__blobs">
<div class="sp-17__blob"></div>
<div class="sp-17__blob"></div>
<div class="sp-17__blob"></div>
</div>
<div class="sp-17__glass">
<div class="sp-17__arc"></div>
<div class="sp-17__arc-inner"></div>
</div>
</div>.sp-17,
.sp-17 *,
.sp-17 *::before,
.sp-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sp-17 {
--bg: #1a0533;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: var(--bg);
overflow: hidden;
}
.sp-17__blobs {
position: absolute;
inset: 0;
pointer-events: none;
}
.sp-17__blob {
position: absolute;
border-radius: 50%;
filter: blur(60px);
opacity: 0.6;
animation: sp-17-float 6s ease-in-out infinite;
}
.sp-17__blob:nth-child(1) {
width: 200px;
height: 200px;
background: #7c3aed;
top: -80px;
left: -60px;
animation-delay: 0s;
}
.sp-17__blob:nth-child(2) {
width: 180px;
height: 180px;
background: #ec4899;
bottom: -60px;
right: -40px;
animation-delay: -2s;
}
.sp-17__blob:nth-child(3) {
width: 160px;
height: 160px;
background: #3b82f6;
top: 20%;
right: 10%;
animation-delay: -4s;
}
.sp-17__glass {
position: relative;
width: 100px;
height: 100px;
border-radius: 50%;
background: rgba(255,255,255,0.08);
backdrop-filter: blur(12px);
border: 1px solid rgba(255,255,255,0.2);
box-shadow: 0 8px 32px rgba(0,0,0,0.3),inset 0 1px 0 rgba(255,255,255,0.15);
display: flex;
align-items: center;
justify-content: center;
}
.sp-17__arc {
position: absolute;
inset: 8px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: rgba(255,255,255,0.9);
border-right-color: rgba(255,255,255,0.4);
animation: sp-17-spin 1.1s linear infinite;
}
.sp-17__arc-inner {
position: absolute;
inset: 20px;
border-radius: 50%;
border: 2px solid transparent;
border-bottom-color: rgba(255,255,255,0.7);
animation: sp-17-spin 0.8s linear infinite reverse;
}
@keyframes sp-17-spin {
to {
transform: rotate(360deg);
}
}
@keyframes sp-17-float {
0%,
100% {
transform: translateY(0) scale(1);
}
50% {
transform: translateY(-20px) scale(1.05);
}
}
@media (prefers-reduced-motion: reduce) {
.sp-17__arc,
.sp-17__arc-inner,
.sp-17__blob {
animation: none;
}
}.sp-17,
.sp-17 *,
.sp-17 *::before,
.sp-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sp-17 {
--bg: #1a0533;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: var(--bg);
overflow: hidden;
}
.sp-17__blobs {
position: absolute;
inset: 0;
pointer-events: none;
}
.sp-17__blob {
position: absolute;
border-radius: 50%;
filter: blur(60px);
opacity: 0.6;
animation: sp-17-float 6s ease-in-out infinite;
}
.sp-17__blob:nth-child(1) {
width: 200px;
height: 200px;
background: #7c3aed;
top: -80px;
left: -60px;
animation-delay: 0s;
}
.sp-17__blob:nth-child(2) {
width: 180px;
height: 180px;
background: #ec4899;
bottom: -60px;
right: -40px;
animation-delay: -2s;
}
.sp-17__blob:nth-child(3) {
width: 160px;
height: 160px;
background: #3b82f6;
top: 20%;
right: 10%;
animation-delay: -4s;
}
.sp-17__glass {
position: relative;
width: 100px;
height: 100px;
border-radius: 50%;
background: rgba(255,255,255,0.08);
backdrop-filter: blur(12px);
border: 1px solid rgba(255,255,255,0.2);
box-shadow: 0 8px 32px rgba(0,0,0,0.3),inset 0 1px 0 rgba(255,255,255,0.15);
display: flex;
align-items: center;
justify-content: center;
}
.sp-17__arc {
position: absolute;
inset: 8px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: rgba(255,255,255,0.9);
border-right-color: rgba(255,255,255,0.4);
animation: sp-17-spin 1.1s linear infinite;
}
.sp-17__arc-inner {
position: absolute;
inset: 20px;
border-radius: 50%;
border: 2px solid transparent;
border-bottom-color: rgba(255,255,255,0.7);
animation: sp-17-spin 0.8s linear infinite reverse;
}
@keyframes sp-17-spin {
to {
transform: rotate(360deg);
}
}
@keyframes sp-17-float {
0%,
100% {
transform: translateY(0) scale(1);
}
50% {
transform: translateY(-20px) scale(1.05);
}
}
@media (prefers-reduced-motion: reduce) {
.sp-17__arc,
.sp-17__arc-inner,
.sp-17__blob {
animation: none;
}
}Here's a working CSS Spinner from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Glassmorphism Loader Spinner
Source: https://codefronts.com/motion/css-spinner-designs/glassmorphism-loader-spinner/
A frosted-glass circle with backdrop-filter blur floats over animated colour blobs, with two nested arcs spinning at different speeds to create a layered glassmorphic loading indicator.
## HTML
```html
<div class="sp-17">
<div class="sp-17__blobs">
<div class="sp-17__blob"></div>
<div class="sp-17__blob"></div>
<div class="sp-17__blob"></div>
</div>
<div class="sp-17__glass">
<div class="sp-17__arc"></div>
<div class="sp-17__arc-inner"></div>
</div>
</div>
```
## CSS
```css
.sp-17,
.sp-17 *,
.sp-17 *::before,
.sp-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sp-17 {
--bg: #1a0533;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: var(--bg);
overflow: hidden;
}
.sp-17__blobs {
position: absolute;
inset: 0;
pointer-events: none;
}
.sp-17__blob {
position: absolute;
border-radius: 50%;
filter: blur(60px);
opacity: 0.6;
animation: sp-17-float 6s ease-in-out infinite;
}
.sp-17__blob:nth-child(1) {
width: 200px;
height: 200px;
background: #7c3aed;
top: -80px;
left: -60px;
animation-delay: 0s;
}
.sp-17__blob:nth-child(2) {
width: 180px;
height: 180px;
background: #ec4899;
bottom: -60px;
right: -40px;
animation-delay: -2s;
}
.sp-17__blob:nth-child(3) {
width: 160px;
height: 160px;
background: #3b82f6;
top: 20%;
right: 10%;
animation-delay: -4s;
}
.sp-17__glass {
position: relative;
width: 100px;
height: 100px;
border-radius: 50%;
background: rgba(255,255,255,0.08);
backdrop-filter: blur(12px);
border: 1px solid rgba(255,255,255,0.2);
box-shadow: 0 8px 32px rgba(0,0,0,0.3),inset 0 1px 0 rgba(255,255,255,0.15);
display: flex;
align-items: center;
justify-content: center;
}
.sp-17__arc {
position: absolute;
inset: 8px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: rgba(255,255,255,0.9);
border-right-color: rgba(255,255,255,0.4);
animation: sp-17-spin 1.1s linear infinite;
}
.sp-17__arc-inner {
position: absolute;
inset: 20px;
border-radius: 50%;
border: 2px solid transparent;
border-bottom-color: rgba(255,255,255,0.7);
animation: sp-17-spin 0.8s linear infinite reverse;
}
@keyframes sp-17-spin {
to {
transform: rotate(360deg);
}
}
@keyframes sp-17-float {
0%,
100% {
transform: translateY(0) scale(1);
}
50% {
transform: translateY(-20px) scale(1.05);
}
}
@media (prefers-reduced-motion: reduce) {
.sp-17__arc,
.sp-17__arc-inner,
.sp-17__blob {
animation: none;
}
}
```Here's a working CSS Spinner from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Glassmorphism Loader Spinner
Source: https://codefronts.com/motion/css-spinner-designs/glassmorphism-loader-spinner/
A frosted-glass circle with backdrop-filter blur floats over animated colour blobs, with two nested arcs spinning at different speeds to create a layered glassmorphic loading indicator.
## HTML
```html
<div class="sp-17">
<div class="sp-17__blobs">
<div class="sp-17__blob"></div>
<div class="sp-17__blob"></div>
<div class="sp-17__blob"></div>
</div>
<div class="sp-17__glass">
<div class="sp-17__arc"></div>
<div class="sp-17__arc-inner"></div>
</div>
</div>
```
## CSS
```css
.sp-17,
.sp-17 *,
.sp-17 *::before,
.sp-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sp-17 {
--bg: #1a0533;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: var(--bg);
overflow: hidden;
}
.sp-17__blobs {
position: absolute;
inset: 0;
pointer-events: none;
}
.sp-17__blob {
position: absolute;
border-radius: 50%;
filter: blur(60px);
opacity: 0.6;
animation: sp-17-float 6s ease-in-out infinite;
}
.sp-17__blob:nth-child(1) {
width: 200px;
height: 200px;
background: #7c3aed;
top: -80px;
left: -60px;
animation-delay: 0s;
}
.sp-17__blob:nth-child(2) {
width: 180px;
height: 180px;
background: #ec4899;
bottom: -60px;
right: -40px;
animation-delay: -2s;
}
.sp-17__blob:nth-child(3) {
width: 160px;
height: 160px;
background: #3b82f6;
top: 20%;
right: 10%;
animation-delay: -4s;
}
.sp-17__glass {
position: relative;
width: 100px;
height: 100px;
border-radius: 50%;
background: rgba(255,255,255,0.08);
backdrop-filter: blur(12px);
border: 1px solid rgba(255,255,255,0.2);
box-shadow: 0 8px 32px rgba(0,0,0,0.3),inset 0 1px 0 rgba(255,255,255,0.15);
display: flex;
align-items: center;
justify-content: center;
}
.sp-17__arc {
position: absolute;
inset: 8px;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: rgba(255,255,255,0.9);
border-right-color: rgba(255,255,255,0.4);
animation: sp-17-spin 1.1s linear infinite;
}
.sp-17__arc-inner {
position: absolute;
inset: 20px;
border-radius: 50%;
border: 2px solid transparent;
border-bottom-color: rgba(255,255,255,0.7);
animation: sp-17-spin 0.8s linear infinite reverse;
}
@keyframes sp-17-spin {
to {
transform: rotate(360deg);
}
}
@keyframes sp-17-float {
0%,
100% {
transform: translateY(0) scale(1);
}
50% {
transform: translateY(-20px) scale(1.05);
}
}
@media (prefers-reduced-motion: reduce) {
.sp-17__arc,
.sp-17__arc-inner,
.sp-17__blob {
animation: none;
}
}
```How this works
Three large radial-gradient blobs are positioned in the background and animated with a slow floating keyframe (sp-17-float) that nudges them up and down. Their filter:blur(60px) softens them into smooth colour pools. The glass disc uses backdrop-filter:blur(12px) and a semi-transparent white background to frost the blobs visible beneath, plus a border:1px solid rgba(255,255,255,0.2) to define the glass edge.
Inside the disc, two arcs (outer and inner) spin at different speeds (1.1s and 0.8s) and directions, using the same transparent-border technique but with semi-transparent white strokes to maintain the glass aesthetic without colour bleeding.
Make it yours
- Change blob colours (
#7c3aed,#ec4899,#3b82f6) to shift the overall colour temperature of the frosted background. - Increase
backdrop-filter:blur()from12pxto24pxfor a more heavily frosted glass; decrease to4pxfor a subtle tint. - Add a fourth blob at a different position and animation phase to increase colour variety behind the glass.
- Replace the two arc spinners with a single conic-gradient spinner for a different inner mechanic while keeping the glass shell.
- Add
box-shadow:0 8px 32px rgba(0,0,0,0.5)to deepen the glass disc's shadow cast on the background.
Gotchas — read before shipping
backdrop-filter:blur()requires the element to be on its own stacking context — ensure no ancestor hastransformorfilterthat would break the backdrop reference in Safari.- Older Safari (pre-15.4) requires
-webkit-backdrop-filterprefix alongside the standard property — add both for full coverage. - The floating blobs use
filter:blur(60px)which forces GPU rasterisation of large elements; on mobile, reduce blur radius or use smaller blob dimensions to reduce memory pressure.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 76+ | 14+ | 103+ | 76+ |
backdrop-filter requires Chrome 76+, Safari 14+, Firefox 103+; add -webkit- prefix for Safari 9-13.