From Pen to Path: Writing an SVG Heart by Hand

Valentine’s Day brings its usual flood of heart-shaped everything. Earlier, we rounded up many ways to draw hearts in HTML and CSS, and readers delivered some beautiful implementations. But there’s a more deliberate, crafty way to express affection: hand-drawing your own SVG shape line by line. No vector editor required—just a text editor and an understanding of coordinates. (If you prefer, you can also use the modern CSS shape() function for this effect; there’s a demo of that approach.)

Start with a blank HTML document and drop in an <svg> element:

<svg>

</svg>

To see what we’re doing inside the vector realm, we add a viewBox attribute. The SVG coordinate plane stretches infinitely along an x-axis and y-axis, much like math class. We’ll set its bounds from 0 0 to 10 10, creating a square drawing area:

diagram depicting a viewbox drawn on a graph

The viewBox takes those coordinates as a string of space-separated values:

<svg viewBox="0 0 10 10">

</svg>

Note that SVG ignores pixel-based units like px or rem here; this is vector space, where coordinates are the only currency.

Drawing Segments with Path Commands

To render our heart, we use the <path> element, whose d attribute holds a series of drawing commands. There are several path command categories, some harder to keep straight than others:

  • MoveTo: M, m
  • LineTo: L, l, H, h, V, v
  • Cubic Bézier curve: C, c, S, s
  • Quadratic Bézier curve: Q, q, T, t
  • Elliptical arc curve: A, a
  • ClosePath: Z, z

For an outline heart, we only need the first two. Think of MoveTo as lifting your pen and positioning it at the starting point—no ink hits the paper yet. To move to coordinates (2,2), the d value becomes M2,2:

<svg viewBox="0 0 10 10">
  <path d="M2,2" />
</svg>

LineTo, on the other hand, is the act of drawing the line itself from the current point to a new one. Adding L4,4 extends our line to the middle of the shape:

<svg viewBox="0 0 10 10">
  <path d="M2,2 L4,4" />
</svg>

Repeat with L6,2 to finish the top half of the heart on the right side:

<svg viewBox="0 0 10 10">
  <path d="M2,2 L4,4 L6,2" />
</svg>
diagram of line segments drawn on a graph

A preview at this stage shows an upside-down triangle, because SVG applies a default fill to closed shapes. Remove the interior fill entirely with fill="none":

<svg viewBox="0 0 10 10">
  <path d="M2,2 L4,4 L6,2" fill="none" />
</svg>

Now add visibility to the outline with a colored stroke:

<svg viewBox="0 0 10 10">
  <path 
    d="M2,2 L4,4 L6,2" 
    fill="none" 
    stroke="rebeccapurple" />
</svg>

Increase the thickness of that stroke with a larger stroke-width:

<svg viewBox="0 0 10 10">
  <path 
    d="M2,2 L4,4 L6,2" 
    fill="none" 
    stroke="rebeccapurple" 
    stroke-width="4" />
</svg>

Finally, set stroke-linecap to round so the two endpoints of the line curve smoothly, turning the V-shaped sketch into the familiar silhouette of a heart:

<svg viewBox="0 0 10 10">
  <path 
    d="M2,2 L4,4 L6,2" 
    fill="none"
    stroke="rebeccapurple"
    stroke-width="4"
    stroke-linecap="round" />
</svg>

The hand-drawn heart is complete—no auxiliary tools involved, just a few path commands with something to say.

💜