25 CSS Spinners08 / 25
Morph Square-to-Circle Spinner
A hollow square morphs fluidly through four asymmetric border-radius stages into a perfect circle and back, while simultaneously rotating — a classic CSS shape-morphing technique.
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-08">
<div class="sp-08__outer">
<div class="sp-08__track"></div>
<div class="sp-08__shape"></div>
</div>
</div><div class="sp-08">
<div class="sp-08__outer">
<div class="sp-08__track"></div>
<div class="sp-08__shape"></div>
</div>
</div>.sp-08,
.sp-08 *,
.sp-08 *::before,
.sp-08 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sp-08 {
--bg: #0e0e12;
--c: #ff9100;
--glow: rgba(255,145,0,0.4);
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: var(--bg);
}
.sp-08__shape {
width: 60px;
height: 60px;
background: transparent;
border: 4px solid var(--c);
filter: drop-shadow(0 0 8px var(--glow));
animation: sp-08-morph 2s ease-in-out infinite, sp-08-spin 2s linear infinite;
}
@keyframes sp-08-morph {
0%,
100% {
border-radius: 4px;
transform: rotate(0deg) scale(1);
}
25% {
border-radius: 50% 4px 50% 4px;
}
50% {
border-radius: 50%;
transform: rotate(180deg) scale(1.15);
}
75% {
border-radius: 4px 50% 4px 50%;
}
}
@keyframes sp-08-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.sp-08__outer {
position: relative;
width: 80px;
height: 80px;
display: flex;
align-items: center;
justify-content: center;
}
.sp-08__track {
position: absolute;
inset: 0;
border-radius: 50%;
border: 1px solid rgba(255,145,0,0.1);
}
@media (prefers-reduced-motion: reduce) {
.sp-08__shape {
animation: none;
border-radius: 8px;
}
}.sp-08,
.sp-08 *,
.sp-08 *::before,
.sp-08 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sp-08 {
--bg: #0e0e12;
--c: #ff9100;
--glow: rgba(255,145,0,0.4);
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: var(--bg);
}
.sp-08__shape {
width: 60px;
height: 60px;
background: transparent;
border: 4px solid var(--c);
filter: drop-shadow(0 0 8px var(--glow));
animation: sp-08-morph 2s ease-in-out infinite, sp-08-spin 2s linear infinite;
}
@keyframes sp-08-morph {
0%,
100% {
border-radius: 4px;
transform: rotate(0deg) scale(1);
}
25% {
border-radius: 50% 4px 50% 4px;
}
50% {
border-radius: 50%;
transform: rotate(180deg) scale(1.15);
}
75% {
border-radius: 4px 50% 4px 50%;
}
}
@keyframes sp-08-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.sp-08__outer {
position: relative;
width: 80px;
height: 80px;
display: flex;
align-items: center;
justify-content: center;
}
.sp-08__track {
position: absolute;
inset: 0;
border-radius: 50%;
border: 1px solid rgba(255,145,0,0.1);
}
@media (prefers-reduced-motion: reduce) {
.sp-08__shape {
animation: none;
border-radius: 8px;
}
}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: Morph Square-to-Circle Spinner
Source: https://codefronts.com/motion/css-spinner-designs/morph-square-to-circle-spinner/
A hollow square morphs fluidly through four asymmetric border-radius stages into a perfect circle and back, while simultaneously rotating — a classic CSS shape-morphing technique.
## HTML
```html
<div class="sp-08">
<div class="sp-08__outer">
<div class="sp-08__track"></div>
<div class="sp-08__shape"></div>
</div>
</div>
```
## CSS
```css
.sp-08,
.sp-08 *,
.sp-08 *::before,
.sp-08 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sp-08 {
--bg: #0e0e12;
--c: #ff9100;
--glow: rgba(255,145,0,0.4);
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: var(--bg);
}
.sp-08__shape {
width: 60px;
height: 60px;
background: transparent;
border: 4px solid var(--c);
filter: drop-shadow(0 0 8px var(--glow));
animation: sp-08-morph 2s ease-in-out infinite, sp-08-spin 2s linear infinite;
}
@keyframes sp-08-morph {
0%,
100% {
border-radius: 4px;
transform: rotate(0deg) scale(1);
}
25% {
border-radius: 50% 4px 50% 4px;
}
50% {
border-radius: 50%;
transform: rotate(180deg) scale(1.15);
}
75% {
border-radius: 4px 50% 4px 50%;
}
}
@keyframes sp-08-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.sp-08__outer {
position: relative;
width: 80px;
height: 80px;
display: flex;
align-items: center;
justify-content: center;
}
.sp-08__track {
position: absolute;
inset: 0;
border-radius: 50%;
border: 1px solid rgba(255,145,0,0.1);
}
@media (prefers-reduced-motion: reduce) {
.sp-08__shape {
animation: none;
border-radius: 8px;
}
}
```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: Morph Square-to-Circle Spinner
Source: https://codefronts.com/motion/css-spinner-designs/morph-square-to-circle-spinner/
A hollow square morphs fluidly through four asymmetric border-radius stages into a perfect circle and back, while simultaneously rotating — a classic CSS shape-morphing technique.
## HTML
```html
<div class="sp-08">
<div class="sp-08__outer">
<div class="sp-08__track"></div>
<div class="sp-08__shape"></div>
</div>
</div>
```
## CSS
```css
.sp-08,
.sp-08 *,
.sp-08 *::before,
.sp-08 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.sp-08 {
--bg: #0e0e12;
--c: #ff9100;
--glow: rgba(255,145,0,0.4);
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: var(--bg);
}
.sp-08__shape {
width: 60px;
height: 60px;
background: transparent;
border: 4px solid var(--c);
filter: drop-shadow(0 0 8px var(--glow));
animation: sp-08-morph 2s ease-in-out infinite, sp-08-spin 2s linear infinite;
}
@keyframes sp-08-morph {
0%,
100% {
border-radius: 4px;
transform: rotate(0deg) scale(1);
}
25% {
border-radius: 50% 4px 50% 4px;
}
50% {
border-radius: 50%;
transform: rotate(180deg) scale(1.15);
}
75% {
border-radius: 4px 50% 4px 50%;
}
}
@keyframes sp-08-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.sp-08__outer {
position: relative;
width: 80px;
height: 80px;
display: flex;
align-items: center;
justify-content: center;
}
.sp-08__track {
position: absolute;
inset: 0;
border-radius: 50%;
border: 1px solid rgba(255,145,0,0.1);
}
@media (prefers-reduced-motion: reduce) {
.sp-08__shape {
animation: none;
border-radius: 8px;
}
}
```How this works
A single element uses two simultaneous animations: sp-08-morph drives the border-radius through four stages (sharp square → two-corner pill → circle → opposing two-corner pill → back), while sp-08-spin rotates the element 360° over the same period. Because both share the same 2s duration, the morph stages align with compass-point rotations, making the shape appear to tumble.
The element is otherwise a transparent rectangle with a coloured border and a filter:drop-shadow glow, so the shape outline is the primary visual. No child elements are needed — all motion is driven by the single div's transform and border-radius keyframes.
Make it yours
- Change the shape at each morph stage by editing the four
border-radiuskeyframe values — try a star-like40% 60% 60% 40% / 60% 30% 70% 40%for organic forms. - Make the shape solid by replacing
borderwithbackground:var(--c)and removing the border declarations. - Add a second counter-rotating copy at 50% opacity for a yin-yang-like interference pattern.
- Set
animation-timing-function:steps(4,end)to snap between shapes for a retro, frame-by-frame feel. - Reduce the element size to
40pxfor a compact inline spinner that fits in button labels.
Gotchas — read before shipping
- Two simultaneous animation references on a single element in the CSS shorthand (
animation: a 2s ..., b 2s ...) must share timing values carefully — any mismatch causes the morph and spin to drift out of sync. filter:drop-shadowrepaints on every frame during a morph since the painted shape changes —box-shadowis cheaper but only follows the border-box, not the morphed outline.border-radiusanimation is interpolated by the CSS engine which can look jerky at large step changes; keep adjacent keyframe values close (within 20–30%) for smooth transitions.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 60+ | 12+ | 60+ | 60+ |
Multi-value border-radius animation is well-supported across all modern engines.