Shape Morph Transition
A single 80 px shape that goes from circle to blob, then to rounded square and back, turning a full circle and breathing from 0.9 to 1.1: eight border-radius values interpolated (the syntax with "/"), 6 s loop — pure CSS, zero JavaScript, a still circle when the user reduces motion.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Transitions has 52 effects, including 9 free. Explore the category →
3 usage examples



How it works
The .md-morph-stage frame (at least 300 px tall, background #0a0a0f) centers .md-shape-morph, which holds the .md-morph-shape shape: 80 × 80 px, an indigo to cyan gradient (#6366f1 → #06b6d4), border-radius: 50% at rest. It loops mdMorphShape, 6 s, ease-in-out, in five steps: 0% circle; 25% blob 30% 70% 70% 30% / 30% 30% 70% 70%, turned 90° and grown to 1.1; 50% square with 10% corners, turned 180° and shrunk to 0.9; 75% the reverse blob 70% 30% 30% 70% / 70% 70% 30% 30%, at 270° and 1.1; 100% back to the circle after a full turn.
The secret of the organic shape is the slash: before it, the horizontal radii of the four corners; after it, the vertical radii. Eight independent values give elliptical corners, not just round ones, and the browser interpolates each one separately between two steps: the shape moves from one state to the next without a jump, with no SVG or JavaScript. Measured in Chromium 151, Firefox 153 and WebKit 26: four different shapes recorded 0.7 s apart, top-left corner radius at 39% around 0.8 s. Rotation and scale go through transform, computed without any layout recalculation; border-radius requires repainting the shape each frame, which stays light for an element of this size.
The effect is a loop: it says "it is changing, it is alive, it is heating" for as long as the state lasts. For a transition that stops on a specific shape, freeze the keyframe at the chosen step (see the FAQ), as the three examples do. The frame has its own class, prefixed like the rest of the effect: two effects from the library pasted on the same page do not overwrite each other.
Accessibility
- Reduced motion: under
prefers-reduced-motion: reduce, the animation is removed and the shape stays a still circle (the baseborder-radius: 50%). Measured in Chromium 151, Firefox 153 and WebKit 26: animationnone, 50% radius, no transform. - Stopping: the loop runs endlessly. Motion lasting more than 5 seconds must be stoppable: keep the effect for a short-lived state (heating, an analysis), freeze it when the state changes, or add a pause button that sets
animation-play-state: paused. - Meaning: the shape is an empty
div. If its look carries information (round = glass, square = paper), also write it as text: the shape alone cannot be read by a screen reader, nor by everyone. - Content inside the shape: anything you put inside turns with it (a full turn per cycle) and becomes unreadable. Put text or a face in a sibling layer placed on top, like the mascot in example 2.
Browser compatibility
Pure CSS (@keyframes, eight-value border-radius, transform), 1.2 KB, zero JavaScript. Measured in Chromium 151, Firefox 153 and WebKit 26: same transformation, same still circle under reduced motion. Animating border-radius with the "/" syntax is supported by all current browsers.
Without CSS animations, the shape stays a still circle in an indigo-cyan gradient: the element shows, only the transformation is missing.
The code
HTML structure to paste into your page (the CSS + JS come with Premium):
<div class="md-morph-stage">
<div class="md-shape-morph">
<div class="md-morph-shape"></div>
</div>
</div>
The full HTML + CSS + JS of Shape Morph Transition, ready to paste — plus all 840 effects. Or $299 once, lifetime access.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Shapes (CSS — border-radius at each step) |
circle / blob / 10% square / reverse blob | 50% 50% 50% 50% / 60% 60% 40% 40% gives an egg; 0 a true square. Keep percentages at every step so the interpolation stays smooth. |
Rotation and breathing (CSS — transform) |
a full turn, scale 0.9 to 1.1 | Remove rotate() for a shape that deforms in place (useful if it holds text); scale(1.2) strengthens the breathing. |
Duration (CSS — 6s) |
6 s per cycle | 3 s for a lively transformation; 10 s for a background that lives without drawing the eye. Each step lasts a quarter of the cycle. |
Freeze on a shape (CSS — negative animation-delay + paused) |
none: infinite loop | animation-delay: -3s; animation-play-state: paused freezes exactly the square (50% of 6 s); -1.5s the blob. Remove paused to resume from there. |
Size and color (CSS — .md-morph-shape) |
80 × 80 px, #6366f1 → #06b6d4 gradient |
Since the radii are percentages, the shape keeps its proportions at any size. A radial background adds volume, a colored box-shadow a glow. |
FAQ
animation-delay: -3s; animation-play-state: paused places the animation 3 s into its 6 s cycle, exactly the 50% step (the square), and holds it there. -1.5s gives the blob, 0s the circle. To move from one shape to another smoothly, let the animation run and set paused at the right moment, as the examples on this page do.clip-path: path() or an SVG morph, with paths of identical structure.rotate() from the keyframe (the shape deforms in place, text stays upright), or put the content in a sibling element positioned over the shape, which does not turn. The mascot example keeps its eyes upright that way while the body does its half turn.