← Back to gallery
SVG

SVG Path Command Structure for Morph-Ready Shapes

Authored SVG paths with matching command structure (same M/C/Z command count, same anchor types) so a values list can morph between them via SMIL or CSS d:path() interpolation. Three morph routes — crystal → signal, seal → spark, petal → sigil.

svg-pathpath-morphcommand-paritysmilvalues-listclean-room-pathsprefers-reduced-motion

Path Commands / Clean-room Morph Shapes

SVG Path Command Structure for Morph-Ready Shapes

Clean-room SVG paths share the same command family and point flow so a logo-like shape can morph without self-intersection or imported path data.

Same command count

Crystal to Signal

A faceted crystal shape pulls into a sharper signal mark while keeping one M/C/Z command structure across all keyframes. Author both shapes together and keep point order consistent — retrofitting unrelated paths is fragile.

  • path-morph
  • command parity
  • clean-room

Control point traceable

Seal to Spark

A seal form drifts into a badge form while retaining readable control-point flow. The visual point order is documented through authored constants rather than copied external logo paths.

  • shape-authoring
  • control points
  • logo transition

Asymmetric organic route

Petal to Sigil

A petal-like endpoint twists into an asymmetric sigil while preserving compatible cubic commands. This variant demonstrates why command structure matters more than the final silhouette category — readable trace lines emphasize the path during transformation.

  • organic
  • compatible path
  • shine trace

Morph inspector

Crystal to Signal

  • path-morph
  • command parity
  • clean-room

A faceted crystal shape pulls into a sharper signal mark while keeping one M/C/Z command structure across all keyframes. Author both shapes together and keep point order consistent — retrofitting unrelated paths is fragile.

Helped you ship something? 🐟 Send my cat a churu

/* Sharp logo-style morph with a small scale punch at each endpoint — the shape "lands" briefly before transforming again.
   Intensity 1.00× scales translate / scale punch in CSS.
   Cycle 4.2s. */

@keyframes path-morph-badge-float { /* per-variant in slug css */ }

@media (prefers-reduced-motion: reduce) {
  .morph-shape, .morph-shine { animation: none; }
}

How to make this

A morph-ready SVG path keeps every keyframe on the same command sequence, point order, and viewBox so the browser can interpolate the d attribute without folded in-between shapes.

html
1<svg class="path-command-demo" viewBox="0 0 180 180" role="img"  aria-labelledby="path-command-title path-command-desc">  <title id="path-command-title">Compatible SVG path morph</title>  <desc id="path-command-desc">    Two clean-room badge paths share the same cubic command structure.  </desc>  <defs>    <linearGradient id="path-command-fill" x1="32" x2="148" y1="26" y2="154">      <stop offset="0%" stop-color="#a78bfa" />      <stop offset="100%" stop-color="#67e8f9" />    </linearGradient>  </defs>13  <path class="path-command-demo__ghost"    d="M88 14 C124 22 155 45 160 78 C168 120 130 158 90 160 C50 158 18 126 26 84 C32 48 56 24 88 14 Z" />15  <path class="path-command-demo__ghost path-command-demo__ghost--to"    d="M110 16 C142 44 160 78 142 112 C122 150 70 158 43 128 C20 102 38 58 74 46 C90 40 98 28 110 16 Z" />17  <path class="path-command-demo__shape"    d="M88 14 C124 22 155 45 160 78 C168 120 130 158 90 160 C50 158 18 126 26 84 C32 48 56 24 88 14 Z">19    <animate attributeName="d"      values="M88 14 C124 22 155 45 160 78 C168 120 130 158 90 160 C50 158 18 126 26 84 C32 48 56 24 88 14 Z; M110 16 C142 44 160 78 142 112 C122 150 70 158 43 128 C20 102 38 58 74 46 C90 40 98 28 110 16 Z; M88 14 C124 22 155 45 160 78 C168 120 130 158 90 160 C50 158 18 126 26 84 C32 48 56 24 88 14 Z"      dur="4.6s" repeatCount="indefinite" />  </path>  <path class="path-command-demo__trace" pathLength="1"    d="M88 14 C124 22 155 45 160 78 C168 120 130 158 90 160 C50 158 18 126 26 84 C32 48 56 24 88 14 Z" /></svg> 27<style>.path-command-demo {  width: 180px;  overflow: visible;  filter: drop-shadow(0 0 18px rgba(103, 232, 249, .22));}.path-command-demo__shape {  fill: url(#path-command-fill);  stroke: #cffafe;  stroke-width: 2.5;  stroke-linejoin: round;}.path-command-demo__ghost,.path-command-demo__trace {  fill: none;  stroke-linejoin: round;}.path-command-demo__ghost {  stroke: rgba(167, 139, 250, .5);  stroke-width: 1.5;  stroke-dasharray: 8 9;}.path-command-demo__ghost--to { stroke: rgba(103, 232, 249, .5); }.path-command-demo__trace {  stroke: rgba(248, 250, 252, .9);  stroke-width: 2;  stroke-linecap: round;  stroke-dasharray: .16 .84;  animation: path-command-recipe-trace 4.6s ease-in-out infinite;}@keyframes path-command-recipe-trace {  0%, 100% { stroke-dashoffset: 1; opacity: .28; }59  50% { stroke-dashoffset: 0; opacity: 1; }}@media (prefers-reduced-motion: reduce) {  .path-command-demo__trace { animation: none; opacity: .75; }}</style>

Annotated snippet

  1. Line 1The SVG owns its accessible name because this example is the visual subject. Decorative morphs can use aria-hidden and move the label to adjacent text.
  2. Line 13The first ghost path is not random reference art. It is the exact start silhouette, authored with the same M plus six cubic curves plus Z structure as the morph target.
    PitfallWhy do intermediate shapes fold or pinch?

    The point flow is probably reversed, crossed, or unevenly distributed. Author both endpoints together, keep points moving around the silhouette in the same direction, and avoid retrofitting unrelated exported paths.

  3. Line 15The target path keeps the same command family and point order. The numbers change, but the command grammar does not.
    PitfallCan any two SVG paths morph if they share a viewBox?

    No. A viewBox only aligns coordinate space. The paths still need compatible command sequences and point order, such as M C C C C C C Z to M C C C C C C Z.

  4. Line 17The visible shape starts from the same d value as the first ghost. Keeping endpoints visible helps authors spot folded or reversed intermediate silhouettes.
    PitfallWhy do intermediate shapes fold or pinch?

    The point flow is probably reversed, crossed, or unevenly distributed. Author both endpoints together, keep points moving around the silhouette in the same direction, and avoid retrofitting unrelated exported paths.

  5. Line 19SMIL interpolation on d only stays clean when each value has compatible commands. Same viewBox, same fill, or same rough size is not enough.

    Both cells try the SAME SMIL d-attribute morph — endpoint A → endpoint B → endpoint A. before pairs an "M L L L L Z" polygon with an "M C C C C C C Z" blob — the command sequences do not match, so SMIL cannot interpolate point-by-point and the shape SNAPS between the two states. after pairs two blobs that both use "M C C C C C C Z" — same command count and order, so the morph is a continuous smooth transition.

    PitfallCan any two SVG paths morph if they share a viewBox?

    No. A viewBox only aligns coordinate space. The paths still need compatible command sequences and point order, such as M C C C C C C Z to M C C C C C C Z.

  6. Line 27The trace uses pathLength="1" and a small dash pattern to make the contour readable while the filled shape carries the morph.

    Both contours run the same stroke-dashoffset 0 ↔ 1 animation with the same dash pattern (.16 .84). without pathLength, "1" is a single SVG user unit (~1 px in this 120 unit viewBox) so the dashes barely move. With pathLength="1", the dash pattern maps to the full contour and the highlight visibly travels around the shape.

    PitfallIs SMIL d animation broadly supported?

    Modern Chromium, Firefox, and Safari support SVG animate for path data in practical cases, but path interpolation details are still worth testing on the exact target browsers and paths.

  7. Line 59The media query stops CSS trace motion. In production, also omit the SMIL animate element when reduced motion is requested, as the showcase does with runtime media detection.
    PitfallHow should reduced motion work for SMIL morphs?

    Render a static endpoint instead of the animate element. CSS can stop companion effects, but the most reliable reduced-motion treatment is to omit the SVG animate node in markup or component logic.

Other pitfalls

Are path morphs expensive?
Small badge or icon paths are usually fine. Complex exported logos, filters, many simultaneous morphs, and large glowing SVGs can become expensive. Reduce point count before adding motion.

Notes

Overview

Authored SVG paths with matching command structure (same M / C / Z command counts, same anchor types) so a values= list can morph between them via SMIL <animate> or CSS d: path() interpolation. Three clean-room morph routes: crystal → signal, seal → spark, petal → sigil.

When to use it

Reach for path morph on logo transitions, icon swaps where the silhouettes are intentionally related, and brand animations between sister marks. Skip morphing between unrelated paths — the interpolation will look broken because the control points have no semantic correspondence. Skip imported logo data; authored matching paths beat retrofitting external SVGs every time.

How it works

Both shapes are authored as SVG paths that share the same command-by-command structure: same count of M (moveto), C (cubic Bezier), and Z (closepath) commands in the same order. The interpolator pairs commands by index and tweens the coordinate values between them. With SMIL, use <animate attributeName="d" values="path1; path2; path1" dur="3s" repeatCount="indefinite" /> inside the <path>. With CSS, use @keyframes on the path’s d property: d: path('...') at each keyframe.

Production gotchas

Mismatched command counts produce snap-jumps mid-morph (the interpolator gives up and renders the next path directly). The most common bug: one path uses L (lineto) where the other uses C (curveto) for the same visual segment — even if they look identical at rest, they cannot interpolate. Convert all lineto’s to curveto’s for morph-readiness. Tools like svg-path-commander or flubber can normalize command structure post-hoc but introduce extra control points. CSS d: path() interpolation is not supported in older Safari (< 16) — fall back to SMIL or JS.

Accessibility

Add an SVG <title> describing the morph target (e.g. “Crystal transforming into signal”). Under prefers-reduced-motion: reduce pin the path at its final shape (skip the morph animation entirely) — the user gets the destination state without watching the transformation. Avoid morphs that change the perceived meaning of an icon mid-animation, since screen readers announce the title once.

References

Implementation depth

Morph readiness is authored before animation starts. The paths need matching command counts and compatible anchors so interpolation has meaningful pairs instead of jumping between unrelated coordinate lists.

Normalize imported paths with care. Tools can add points until two shapes technically interpolate, but the visual may still twist if the semantic corners do not line up. Reduced motion should show the destination shape directly.