Handwriting SVG Animation for React

SVG path that draws itself on mount. Pass path for custom shapes or text to render handwriting.

Component

Installation

 

Usage

Import

Add the HandwritingSvg import.

import { HandwritingSvg } from "@/components/handwriting-svg";

Path

Use with path for custom SVG.

<HandwritingSvg path="M50 10 L90 50 L50 90 L10 50 Z" />;

Text

Or use text for handwriting rendering.

<HandwritingSvg text="Hello" />;

Guidelines

  • Use path for custom SVG path data (d attribute).
  • Use text to render text as handwriting; requires fontUrl (default: Indie Flower).
  • Animates on mount. duration and delay control timing.

Props

All props are optional unless marked required. Use these to customize every aspect of the component.

PropTypeDefaultDescription
classNamestring-Additional CSS classes for the SVG (e.g. text-rose-500 for stroke).
strokeClassNamestring-Classes for the animated path stroke.
pathstring-Custom SVG path (d attribute). Use when not using text.
textstring-Text to render as handwriting. Uses opentype.js with fontUrl.
fontUrlstringIndie Flower TTF URLFont URL for text rendering. TTF or OTF.
durationnumber2Draw animation duration in seconds.
delaynumber0.5Delay before animation starts (seconds).
ease"linear" | "easeIn" | "easeOut" | "easeInOut""easeInOut"Animation easing: linear, easeIn, easeOut, easeInOut.
widthnumber100SVG width in pixels.
heightnumber100SVG height in pixels.
fontSizenumber48Font size for text rendering.
strokeWidthnumber2Stroke width in pixels.

Accessibility

  • Purely decorative visual effect with no interactive controls, focusable elements, or keyboard handlers.
  • The SVG is marked aria-hidden so assistive technology skips it; the inline title element is therefore not announced, so convey any meaning conveyed by the drawing through adjacent visible text.
  • When rendering text input the glyphs are drawn as SVG strokes rather than real text, so screen readers receive no readable equivalent and a visible or visually-hidden text label should accompany it.
  • The component does not check prefers-reduced-motion, so the draw-on-mount animation always plays; it should be guarded with a reduced-motion query that renders the final path immediately for users who prefer reduced motion.

Performance

  • Animates only the SVG pathLength via framer-motion, which drives stroke-dasharray and stroke-dashoffset; this avoids layout and paint of geometry but stroke-dashoffset is not GPU-composited, so it repaints each frame.
  • Animation runs once on mount only with no scroll or visibility gating, so offscreen instances still animate; an IntersectionObserver could defer work until visible.
  • Text rendering performs a network font fetch through opentype.js in a useEffect, gated behind a loading state, and uses a cancelled flag in the cleanup to avoid setting state after unmount.
  • No requestAnimationFrame, timers, event listeners, IntersectionObserver, or will-change hints are used, so there are no manual listeners or timers to leak beyond the single fetch guarded by the cleanup.

Examples

Path

Custom SVG path draws on mount.

import { HandwritingSvg } from "@/components/handwriting-svg";

<HandwritingSvg path="M50 85 C20 60 5 35 25 15 C40 0 50 15 50 15 C50 15 60 0 75 15 C95 35 80 60 50 85 Z" />;

Text input

Text rendered as handwriting using a font.

import { HandwritingSvg } from "@/components/handwriting-svg";

<HandwritingSvg text="Hi" className="text-amber-500" />
<HandwritingSvg text="Hello" width={120} height={60} />

Custom input

Type your name and click Draw to see it rendered as handwriting.

import { HandwritingSvg } from "@/components/handwriting-svg";

<HandwritingSvg text="Pulkit" />;

Last updated on Jun 19

Made with ❤️ by Pulkit &

© 2026 Pulkit. All rights reserved

Last updated: