← Back to gallery
SVG

Signature Line Drawing Illusion Overview

Handwritten signature illusion drawn via stroke-dasharray timing curves that mimic a real pen's pacing. Three signatures — a relaxed cursive, a confident architect's mark, and a slow editorial scribble — each with its own pen-pressure rhythm.

svg-pathsignaturestroke-dasharraystroke-dashoffsethandwritingeasing-curveprefers-reduced-motion

Signature draw · stroke-dashoffset

Signature Line Drawing Illusion

Long dash arrays and offset animation reveal authored signature strokes in sequence, creating a pen-draw illusion without importing external handwriting assets. Three variants demonstrate compact initials, a multi-stroke receipt signoff, and a looping approval mark.

Cursive M · single-letter initial

Initial Mark

A stylized cursive "M" — three peaks drawn as one continuous flowing stroke, then a small flourish underline beneath it. The kind of single-letter initial someone might scrawl on a tablet to acknowledge a notification.

  • cursive M
  • monogram
  • two strokes

Cursive name · flowing signature

Receipt Signoff

A full cursive name signature — flowing left-to-right handwriting with two visible pen-lifts (first-letter loop, body waveform, trailing flourish) and a finishing underline beneath. Reads as a real signed name.

  • cursive
  • pen lift
  • underline

Checkmark inside circle

Approval Seal

A universal "approved" stamp — a closing circle drawn first, then a checkmark drawn inside it. The two strokes read in clear order so the gesture lands as confirmation.

  • checkmark
  • circle
  • approved

Signature inspector

Initial Mark

  • cursive M
  • monogram
  • two strokes

A stylized cursive "M" — three peaks drawn as one continuous flowing stroke, then a small flourish underline beneath it. The kind of single-letter initial someone might scrawl on a tablet to acknowledge a notification.

Helped you ship something? 🐟 Send my cat a churu

.signature-stage__stroke {
  fill: none;
  stroke: var(--signature-accent);
  stroke-width: 5px;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  opacity: 0;
  animation: signatureDraw 5.20s cubic-bezier(0.55, 0.05, 0.35, 0.95) infinite;
  /* per-stroke stagger lifts each path in writing order */
  animation-delay: calc(var(--signature-stroke-index, 0) * 140ms);
}

.signature-stage__stroke--thin {
  stroke-width: 3px;
  stroke: var(--signature-accent-2);
}

/* Phase shape mirrors the gallery card-preview signatureCardDraw
   so the detail-page strokes share the same beat as the thumbnail:
   appear → draw → hold → fade out → invisible reset. */
@keyframes signatureDraw {
  0%, 6%    { stroke-dashoffset: 1; opacity: 0; }
  14%       { stroke-dashoffset: 1; opacity: 1; }
  46%       { stroke-dashoffset: 0; opacity: 1; }
  82%       { stroke-dashoffset: 0; opacity: 1; }
  92%, 100% { stroke-dashoffset: 0; opacity: 0; }
}

How to make this

A signature drawing illusion normalizes each authored SVG stroke with pathLength="1", hides it with dashoffset, then reveals strokes in pen-lift order with staggered delays.

html
1<figure class="signature-recipe" aria-labelledby="signature-recipe-caption">2  <svg class="signature-recipe__svg" viewBox="0 0 180 180" aria-hidden="true">    <path class="signature-recipe__stroke"      d="M22 108 C22 70 36 58 50 70 C62 82 56 102 40 104 C28 105 26 96 36 92"5      pathLength="1" style="--stroke-index: 0" />    <path class="signature-recipe__stroke"      d="M36 92 C52 80 62 102 76 92 C90 82 100 102 114 92 C128 82 138 102 150 96"      pathLength="1" style="--stroke-index: 1" />    <path class="signature-recipe__stroke"      d="M150 96 C160 90 166 102 162 114 C158 120 152 116 152 110"      pathLength="1" style="--stroke-index: 2" />    <path class="signature-recipe__stroke signature-recipe__stroke--thin"      d="M26 134 C60 142 110 142 158 132"      pathLength="1" style="--stroke-index: 3" />  </svg>  <figcaption id="signature-recipe-caption">Signed and approved</figcaption></figure> <style>.signature-recipe {  display: inline-grid;  justify-items: center;  gap: .5rem;  color: #e0f2fe;  font: 700 .9rem/1.2 ui-sans-serif, system-ui;}.signature-recipe__svg {  width: 180px;  overflow: visible;  filter: drop-shadow(0 0 14px rgba(240, 171, 252, .22));}.signature-recipe__stroke {  fill: none;  stroke: #f0abfc;35  stroke-width: 5;  stroke-linecap: round;  stroke-linejoin: round;  stroke-dasharray: 1;  stroke-dashoffset: 1;  opacity: 0;  animation: signature-recipe-draw 5.2s cubic-bezier(.55,.05,.35,.95) infinite;42  animation-delay: calc(var(--stroke-index) * 220ms);}.signature-recipe__stroke--thin {  stroke: #93c5fd;  stroke-width: 3;}48@keyframes signature-recipe-draw {  0%, 6% { stroke-dashoffset: 1; opacity: 0; }  14% { stroke-dashoffset: 1; opacity: 1; }  46% { stroke-dashoffset: 0; opacity: 1; }  82% { stroke-dashoffset: 0; opacity: 1; }  92%, 100% { stroke-dashoffset: 0; opacity: 0; }}55@media (prefers-reduced-motion: reduce) {  .signature-recipe__stroke {    animation: none;    stroke-dashoffset: 0;    opacity: 1;  }}</style>

Annotated snippet

  1. Line 1Use surrounding text for the real meaning. A signature flourish is visual confirmation; the figcaption carries the readable state.
  2. Line 2The SVG is aria-hidden because the caption already names the result. Do not make assistive technology traverse decorative handwriting paths.
  3. Line 5pathLength="1" normalizes each different stroke, so dasharray and dashoffset can use the same values on the loop, body, hook, and underline.
  4. Line 35Round caps and joins make short dashoffset reveals look like ink instead of clipped vector segments.

    Same path, same draw animation. stroke-linecap: butt leaves the dashoffset reveal with hard rectangular ends — it reads as a clipped vector wipe. Round caps give the ink a soft pen-tip start and finish.

    PitfallWhy does my signature draw unevenly?

    Different paths have different physical lengths. Add pathLength="1" to each path so stroke-dasharray: 1 and stroke-dashoffset: 1 represent the full stroke on every segment.

  5. Line 42The stagger is driven by a per-path index. That creates the pen-lift illusion without JavaScript timers.

    Same two strokes, same color, same draw keyframe. Without stagger, both paths draw at the same time and read as a wipe. After waits for the first path to finish before starting, creating a visible pen-lift between strokes.

    PitfallCan I use a handwriting font instead of authored paths?

    A font can look handwritten, but the drawing illusion needs stroke geometry. Convert or author the strokes as SVG paths, simplify them, and keep each pen-lift as a separate path.

  6. Line 48The keyframe draws early, holds the completed signature, then fades before reset. The hold is what lets the mark read as a signed state.
    PitfallAre signature draw animations expensive?

    A few simplified paths are cheap. Dense handwriting exports with hundreds of points, glow filters, and many simultaneous signatures can hurt paint performance, especially on low-end mobile devices.

  7. Line 55Reduced motion skips the writing sequence and exposes the completed signature immediately.
    PitfallShould the signature SVG announce anything?

    Usually no. Keep decorative signature paths aria-hidden and expose the actual approval, name, or status as text. The animation should not be the only confirmation.

Other pitfalls

Which browsers support this dashoffset approach?
Modern Chromium, Firefox, and Safari support SVG stroke-dasharray, stroke-dashoffset, and pathLength. If a pathLength edge case appears, the fallback is a visible static signature.
Advanced

Bake stroke thickness into the shape and reveal with a mask

Same arc path, same reveal cycle. BEFORE animates stroke-width on a stroked path — the entire visible stroke widens at the peak frame and thins back out as the keyframe ends, so the previously-drawn thick part loses its weight. AFTER fills a tapered polygon (thin at the endpoints, thick at the peak) and reveals it through a wide mask sweep — each point keeps its baked thickness, so the previously-drawn parts stay exactly as drawn.

View explanation and full code68 lines

Animating stroke-width pulses the entire visible stroke together — parts that were thick a moment ago thin back out as the keyframe ends, because stroke-width is one value for the whole path. The fix is to bake thickness into the geometry: each stroke becomes a filled polygon whose outline encodes the taper (thin at the endpoints, thick at the peak), and a separate wide mask stroke sweeps along the centerline to progressively reveal the ink. The mask decides WHEN each region is visible; the polygon decides HOW THICK each region is, and the polygon never changes. (In production, polygon data typically comes from a tablet capture or vector tool — the simple shapes below demonstrate the technique.)

Paste this as a complete alternative to the base recipe — it uses different SVG geometry (filled polygons + mask), not the same stroked paths.

html
<figure class="signature-recipe" aria-labelledby="signature-recipe-caption">  <svg class="signature-recipe__svg" viewBox="0 0 240 110" aria-hidden="true">    <defs>      <mask id="signature-recipe-reveal" maskUnits="userSpaceOnUse">        <rect width="240" height="110" fill="black"/>        <!-- Mask sweeps along each stroke centerline to progressively             reveal the filled ink polygon underneath. -->        <path class="signature-recipe__sweep"              d="M30 75 C60 30 100 20 120 20 C140 20 180 30 210 75"              pathLength="1" fill="none" stroke="white" stroke-width="22"              style="--sweep-index: 0"/>        <path class="signature-recipe__sweep"              d="M30 92 C100 100 160 99 210 93"              pathLength="1" fill="none" stroke="white" stroke-width="12"              style="--sweep-index: 1"/>      </mask>    </defs>    <g class="signature-recipe__ink" mask="url(#signature-recipe-reveal)">      <!-- Body arc: tapered polygon. Thin at endpoints, thick at the           peak. The thickness lives in the path data, not in a stroke           property, so it never changes as the mask reveals it. -->      <path d="M30 73 C60 26 100 12 120 12 C140 12 180 26 210 73               L210 77 C180 38 140 24 120 24 C100 24 60 38 30 77 Z"/>      <!-- Underline: tapered ribbon — same principle, gentler curve. -->      <path d="M30 91 C100 99 160 98 210 92               L210 94 C160 100 100 101 30 93 Z"/>    </g>  </svg>  <figcaption id="signature-recipe-caption">Signed and approved</figcaption></figure> <style>.signature-recipe {  display: inline-grid;  justify-items: center;  gap: .5rem;  color: #e0f2fe;  font: 700 .9rem/1.2 ui-sans-serif, system-ui;}.signature-recipe__svg {  width: 240px;  overflow: visible;  filter: drop-shadow(0 0 14px rgba(240, 171, 252, .22));}.signature-recipe__ink {  fill: #f0abfc;}.signature-recipe__sweep {  stroke-linecap: round;  stroke-linejoin: round;  stroke-dasharray: 1;  stroke-dashoffset: 1;  animation: signature-recipe-reveal 5.2s cubic-bezier(.55,.05,.35,.95) infinite;  animation-delay: calc(var(--sweep-index) * 380ms);}@keyframes signature-recipe-reveal {  0%, 6%    { stroke-dashoffset: 1; }  46%       { stroke-dashoffset: 0; }  82%       { stroke-dashoffset: 0; }  92%, 100% { stroke-dashoffset: 1; }}@media (prefers-reduced-motion: reduce) {  .signature-recipe__sweep {    animation: none;    stroke-dashoffset: 0;  }}</style>

Notes

Overview

Signature illusions trace a handwritten path via stroke-dasharray + stroke-dashoffset animation, with timing curves that mimic the cadence of a real pen (slow at loops, fast between letters). The path is hand-authored once; the timing does the personality.

When to use it

Reach for signature illusions on contract-signing surfaces, author by-lines, hero brand marks, anything where a personal handwritten signal carries weight. Skip it for utility chrome and for branding where the “signature” is actually typed; the draw illusion will read as theatrical.

How it works

The SVG path defining the signature has stroke-dasharray set to its pathLength (a custom attribute) so the dash unit becomes pathLength itself — portable across any actual path geometry. Animate stroke-dashoffset from pathLength down to 0 over the sequence duration. The personality comes from a non-linear timing function: use a multi-stop cubic-bezier that decelerates on the slow loops and accelerates on connecting strokes. For a truly hand-paced effect, split the signature into multiple path segments and chain them with animation-delay.

Production gotchas

Hand-authored signature paths often have hidden lift points (gaps where the pen stops); these render as unnatural pauses without a manual animation-delay between segments. If the signature is one continuous path, you lose the pen-lift rhythm entirely — structure the artwork as multiple<path> elements from the start. Some SVG export tools (Figma, Illustrator) merge paths on export; double-check the SVG source for separate <path> elements before wiring delays.

Accessibility

The signature is decorative — provide an <title> or aria-label on the SVG with the actual name being “signed” (e.g. “Jane Doe”) so screen readers announce who it represents. Under prefers-reduced-motion: reduce reveal the full signature instantly (set stroke-dashoffset: 0) so the brand mark appears without motion. The signature stroke color must meet at least 3:1 contrast against its surface.

References

Implementation depth

A signature reveal is convincing when the path direction matches the way handwriting would actually move. stroke-dashoffset can only hide or reveal along the path; it cannot fix a path authored in the wrong direction.

Use easing sparingly. Real signatures accelerate through simple strokes and slow near corners, but too much spring motion makes the line look like an icon trace rather than handwriting. Reduced motion should show the signed result.