25 CSS Spinners08 / 25

Pure CSSMIT licensed

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

Live Demo
Try it

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>
.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;
  }
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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-radius keyframe values — try a star-like 40% 60% 60% 40% / 60% 30% 70% 40% for organic forms.
  • Make the shape solid by replacing border with background: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 40px for 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-shadow repaints on every frame during a morph since the painted shape changes — box-shadow is cheaper but only follows the border-box, not the morphed outline.
  • border-radius animation 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

ChromeSafariFirefoxEdge
60+12+60+60+

Multi-value border-radius animation is well-supported across all modern engines.

Techniques used in this demo

Search CodeFronts

Loading…