SVGs on the Web
a brief history of web images
The first image format the web broadly supported was GIF, introduced in 1987. It worked, but could only represent 256 colors at once, which made it fine for simple graphics and terrible for photographs. More usefully, it supported multiple frames, which is how GIFs became synonymous with short looping animations decades later.
JPEG arrived in 1992, built for photographs. Its compression algorithm is lossy: it discards detail the eye is least likely to notice, and it is very good at it. A photograph at 90% JPEG quality looks nearly indistinguishable from the original at a fraction of the size. But that same algorithm is catastrophic for line art, text, and sharp-edged graphics. When you compress a screenshot of code as a JPEG, blocky artifacts appear around every character edge.
PNG landed in 1996 as a response to both: lossless compression, full color support, transparency. It became the default for screenshots, icons, and logos: anything that needed crispness and was not a photograph.
WebP and AVIF are modern successors that squeeze more compression out of raster images than JPEG or PNG. Still useful, still fundamentally the same thing underneath: a grid of colored pixels at a fixed resolution. Scale any of them up and you’re just making the pixels bigger.
why SVG is different
SVG stands for Scalable Vector Graphics. It does not describe pixels; it describes instructions. Draw a line from here to there. Fill this enclosed shape. Use this color. The browser calculates what pixels to actually draw at display time, at whatever resolution it needs.
Scale an SVG icon to any size and it stays sharp. A 48×48 viewbox drawn at 4K is still perfectly crisp; the browser re-rasterises the instructions fresh at full resolution.
SVG files are plain text: XML, specifically. That makes them readable, editable without special software, diffable in git, and often tiny. A simple icon is maybe 200–400 bytes. You can paste the whole thing directly into HTML and it renders inline, no network request required.
Most importantly for this site: SVG elements are styleable with CSS. Setting stroke="currentColor" on an SVG means its lines inherit whatever color is set on the parent element. The four page icons here automatically follow the active theme, with the same markup rendering differently depending on whether you are in light, dark, or live mode.
how SVG paths work
Most SVG shapes have dedicated elements: <circle>, <rect>, <line>. The powerful one is <path>, which describes an arbitrary shape through a sequence of drawing commands packed into the d attribute.
The commands read like instructions to a pen on paper:
M x y— move the pen to a point without drawing anythingL x y— draw a line to a pointC x1 y1, x2 y2, x y— draw a cubic bezier curve to(x,y), pulled by two control pointsZ— close the path back to the starting point
A typical hand-drawn shape uses almost entirely C commands. The six numbers in a cubic bezier are the two control point handles; the further they sit from the endpoints, the more dramatic the curve’s bend. Getting an intuition for how control points influence a curve is most of what it takes to hand-write SVG paths.
All coordinates live inside the coordinate system defined by viewBox. viewBox="0 0 48 48" sets the canvas from (0,0) at the top-left to (48,48) at the bottom-right. The browser maps that space to whatever pixel size the element is on screen.
the icons
Every section of this site has a small hand-drawn icon in the top-right corner of its page. They were written as path coordinates directly, with no design tool, no export step, and no tracing. The slight imprecision is intentional: control points placed a little off from where a geometrically exact shape would put them give the curves their hand-drawn quality.
The icons are defined once in a shared data file and referenced wherever they appear, in each section’s page header and in the gallery below. Eight are drawn at the time of writing, two per section; more may be added.
the icons
<svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- envelope body -->
<path d="M 5 13 C 19 11.8, 31 14.3, 43 13 C 44 22, 43.5 32, 43 40 C 30 41.3, 16 39.2, 5 40 C 4.2 31, 5.7 21, 5 13 Z"/>
<!-- sealed flap -->
<path d="M 5 13 C 11 20, 17 26, 24 28 C 31 25.5, 37.5 19.5, 43 13"/>
<!-- fold lines -->
<path d="M 5 40 C 9 35.5, 14 30.5, 19 27"/>
<path d="M 43 40 C 39 35.5, 34 30, 29 27"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- case body -->
<path d="M 5 16 C 17 15, 31 17, 43 16 L 43 43 C 31 44, 17 42, 5 43 Z"/>
<!-- handle -->
<path d="M 15 16 C 15 7, 33 7, 33 16"/>
<!-- handle fittings -->
<path d="M 13 14 L 17 14 L 17 18 L 13 18 Z"/>
<path d="M 31 14 L 35 14 L 35 18 L 31 18 Z"/>
<!-- opening seam -->
<path d="M 5 26 C 17 25, 31 27, 43 26"/>
<!-- clasp -->
<path d="M 20 23 L 28 23 L 28 29 L 20 29 Z"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- shelf base -->
<path d="M 3 42 C 16 43, 31 41.2, 45 42"/>
<!-- book 1 -->
<path d="M 5 16 C 7 14.8, 10.5 16.8, 12 16 C 12.8 25, 12.5 34.5, 12 42 C 10 43, 7 41.5, 5 42 C 4.3 33, 5.6 24, 5 16 Z"/>
<path d="M 5 23 C 7.5 21.8, 10 23.7, 12 23"/>
<!-- book 2 -->
<path d="M 14 20 C 18.5 18.8, 22.5 21, 26 20 C 26.8 28, 26.5 35.5, 26 42 C 22.5 43.2, 18 41.3, 14 42 C 13.3 35, 14.6 27.5, 14 20 Z"/>
<path d="M 14 27 C 18.5 25.8, 22 27.8, 26 27"/>
<path d="M 14 32 C 18.5 33.2, 22 31.2, 26 32"/>
<!-- book 3 -->
<path d="M 29 10 C 32.5 8.7, 36.5 11, 39 10 C 39.8 20.5, 39.5 31.5, 39 42 C 36.5 43.2, 32.5 41.3, 29 42 C 28.3 31, 29.7 20.5, 29 10 Z"/>
<path d="M 29 17 C 32.5 15.8, 36.5 18, 39 17"/>
<path d="M 29 25 C 32.5 26.3, 36 24.2, 39 25"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- barn body -->
<path d="M 7 22 C 18 21.5, 30 22.5, 41 22 L 41 42 C 30 42.5, 18 41.5, 7 42 Z"/>
<!-- gabled roof -->
<path d="M 5 22 C 11 18, 17 13, 24 9 C 31 13, 37 18, 43 22"/>
<!-- hay loft opening in gable -->
<path d="M 20 22 L 20 16 C 20 13, 28 13, 28 16 L 28 22"/>
<!-- door -->
<path d="M 15 42 L 15 31 L 33 31 L 33 42"/>
<!-- door X brace -->
<path d="M 15 31 L 33 42"/>
<path d="M 33 31 L 15 42"/>
<!-- flames -->
<path d="M 9 43 C 8 38, 12 40, 10 34"/>
<path d="M 24 44 C 23 38, 27 41, 25 34"/>
<path d="M 39 43 C 38 38, 42 40, 40 34"/>
<!-- smoke clouds -->
<path d="M 19 9 C 17 7, 14 7, 15 4 C 16 2, 19 3, 19 5 C 20 2, 23 3, 22 6"/>
<path d="M 27 9 C 25 7, 23 6, 24 3 C 25 1, 28 2, 28 5 C 29 2, 32 3, 31 7"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- bow -->
<path d="M 24 3 C 30 3, 34 7, 34 13 C 34 19, 30 23, 24 23 C 18 23, 14 19, 14 13 C 14 7, 18 3, 24 3 Z"/>
<!-- bow inner ring -->
<path d="M 24 7 C 28 7, 30 9, 30 13 C 30 17, 28 19, 24 19 C 20 19, 18 17, 18 13 C 18 9, 20 7, 24 7 Z"/>
<!-- shaft -->
<path d="M 22 23 L 22 45 L 26 45 L 26 23"/>
<!-- teeth -->
<path d="M 26 31 L 32 31 L 32 35 L 26 35"/>
<path d="M 26 38 L 30 38 L 30 42 L 26 42"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- housing -->
<rect x="1" y="5" width="46" height="34" rx="2"/>
<!-- inner frame -->
<rect x="5" y="9" width="38" height="18"/>
<!-- corner screws -->
<circle cx="5" cy="9" r="1.5"/>
<circle cx="43" cy="9" r="1.5"/>
<circle cx="5" cy="35" r="1.5"/>
<circle cx="43" cy="35" r="1.5"/>
<!-- left reel -->
<circle cx="13" cy="18" r="7"/>
<circle cx="13" cy="18" r="2"/>
<!-- right reel -->
<circle cx="35" cy="18" r="7"/>
<circle cx="35" cy="18" r="2"/>
<!-- bottom notch -->
<path d="M 16 39 L 19 33 L 29 33 L 32 39"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- outer crumpled shape -->
<path d="M24 5 C32 3,43 10,44 20 C45 30,40 40,33 43 C26 46,14 44,8 38 C2 32,3 20,7 13 C11 6,16 7,24 5Z"/>
<!-- crease lines -->
<path d="M22 7 C19 16,16 24,10 36"/>
<path d="M38 14 C31 20,27 24,20 40"/>
<path d="M7 24 C16 22,26 24,38 30"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- tilted body -->
<path d="M 13 9 C 22 7, 32 8, 38 11 L 39 37 C 30 40, 18 41, 12 38 Z"/>
<!-- text lines -->
<path d="M 16 18 C 24 17, 32 18, 36 19"/>
<path d="M 15 25 C 23 24, 31 25, 36 26"/>
<path d="M 15 32 C 22 31, 29 32, 34 33"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- saucer base -->
<path d="M 8 43 C 19 41, 29 42, 40 43 C 37 46, 11 46, 8 43 Z"/>
<!-- stem -->
<path d="M 21 38 C 23 37.5, 25 38.5, 27 38 L 27 43 C 25 43.5, 23 42.5, 21 43 Z"/>
<!-- bobeche (drip cup) -->
<path d="M 17 34 C 22 33, 26 34, 31 34 L 31 38 C 26 38.5, 22 37.5, 17 38 Z"/>
<!-- candle body -->
<path d="M 19 11 C 22 10.5, 26 11.5, 29 11 L 29 34 C 26 34.5, 22 33.5, 19 34 Z"/>
<!-- wax drip -->
<path d="M 19 20 C 17 24, 17 28, 18 31"/>
<!-- flame -->
<path d="M 24 3 C 27 6, 28 9, 24 11 C 20 9, 21 6, 24 3 Z"/>
<!-- flame core -->
<path d="M 24 6 C 25.5 8, 26 10, 24 11"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- saucer -->
<path d="M 5 42 C 16 46, 32 46, 43 42"/>
<!-- cup body -->
<path d="M 10 20 C 9 38, 13 41, 24 41 C 35 41, 39 38, 38 20"/>
<!-- rim -->
<path d="M 10 20 C 17 18, 31 18, 38 20"/>
<!-- handle -->
<path d="M 38 25 C 45 25, 45 37, 38 37"/>
<!-- steam left -->
<path d="M 17 16 C 19 12, 15 8, 17 4"/>
<!-- steam right -->
<path d="M 27 15 C 29 11, 25 7, 27 3"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- chip body -->
<path d="M 13 13 C 21 12.2, 28 13.8, 35 13 L 35 35 C 28 35.8, 21 34.2, 13 35 Z"/>
<!-- inner die -->
<path d="M 18 18 C 22 17.5, 26 18.5, 30 18 L 30 30 C 26 30.5, 22 29.5, 18 30 Z"/>
<!-- top pins -->
<path d="M 18 13 L 18 7"/>
<path d="M 24 13 L 24 7"/>
<path d="M 30 13 L 30 7"/>
<!-- bottom pins -->
<path d="M 18 35 L 18 41"/>
<path d="M 24 35 L 24 41"/>
<path d="M 30 35 L 30 41"/>
<!-- left pins -->
<path d="M 13 18 L 7 18"/>
<path d="M 13 24 L 7 24"/>
<path d="M 13 30 L 7 30"/>
<!-- right pins -->
<path d="M 35 18 L 41 18"/>
<path d="M 35 24 L 41 24"/>
<path d="M 35 30 L 41 30"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- card body with clipped top-left corner -->
<path d="M 10 9 C 22 8.5, 33 9.5, 44 9 L 44 39 C 31 39.5, 16 38.5, 4 39 L 4 16 Z"/>
<!-- top print zone line -->
<path d="M 10 9 C 22 12, 33 11, 44 12"/>
<!-- row 1: all 7 holes punched -->
<path d="M 8 15 L 10 15 L 10 20 L 8 20 Z"/>
<path d="M 13 15 L 15 15 L 15 20 L 13 20 Z"/>
<path d="M 18 15 L 20 15 L 20 20 L 18 20 Z"/>
<path d="M 23 15 L 25 15 L 25 20 L 23 20 Z"/>
<path d="M 28 15 L 30 15 L 30 20 L 28 20 Z"/>
<path d="M 33 15 L 35 15 L 35 20 L 33 20 Z"/>
<path d="M 38 15 L 40 15 L 40 20 L 38 20 Z"/>
<!-- row 2: sparse (1 0 1 0 0 1 0) -->
<path d="M 8 23 L 10 23 L 10 28 L 8 28 Z"/>
<path d="M 18 23 L 20 23 L 20 28 L 18 28 Z"/>
<path d="M 33 23 L 35 23 L 35 28 L 33 28 Z"/>
<!-- row 3: alternating (0 1 0 1 0 1 0) -->
<path d="M 13 31 L 15 31 L 15 36 L 13 36 Z"/>
<path d="M 23 31 L 25 31 L 25 36 L 23 36 Z"/>
<path d="M 38 31 L 40 31 L 40 36 L 38 36 Z"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- front face -->
<path d="M 5 18 C 14 16.5, 24 19.3, 32 18 C 33 27, 32.7 36.5, 32 44 C 23 45, 12 43.2, 5 44 C 4.2 35, 5.7 26, 5 18 Z"/>
<!-- top face -->
<path d="M 5 18 C 8 14.8, 10.5 12.2, 13 11 C 21.5 11.7, 30 10.2, 40 11 C 37.8 13, 35 15.5, 32 18 C 22.5 16.8, 13 18.9, 5 18 Z"/>
<!-- right face -->
<path d="M 32 18 C 35.5 15, 38.5 12, 40 11 C 41 19.5, 40.7 29, 40 37 C 37 40, 34.5 42, 32 44 C 32.7 36, 33 27, 32 18 Z"/>
<!-- front X brace -->
<path d="M 5 18 C 14 26.5, 24 36, 32 44"/>
<path d="M 5 44 C 14 36, 23.5 26, 32 18"/>
<!-- right face X -->
<path d="M 32 18 C 35.5 24, 37.5 30.5, 40 37"/>
<path d="M 40 11 C 37.5 21.5, 35.5 32, 32 44"/>
<!-- top plank lines -->
<path d="M 14 18 C 16.5 15.5, 19.5 13, 22 11"/>
<path d="M 23 18 C 26 15.5, 28.5 13, 31 11"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- blade top edge (wider) -->
<path d="M 11 3 L 37 3"/>
<!-- left teeth (edge tapers inward as it descends) -->
<path d="M 11 3 L 8 5 L 11 7 L 8 9 L 11 11 L 8 13 L 12 15 L 9 17 L 12 19 L 9 21 L 13 23 L 10 25 L 13 27 L 10 29 L 14 31 L 11 33 L 15 34"/>
<!-- right teeth (mirror taper) -->
<path d="M 37 3 L 40 5 L 37 7 L 40 9 L 37 11 L 40 13 L 36 15 L 39 17 L 36 19 L 39 21 L 35 23 L 38 25 L 35 27 L 38 29 L 34 31 L 37 33 L 33 34"/>
<!-- shoulder step -->
<path d="M 15 34 L 15 37 L 19 37 L 19 40 L 29 40 L 29 37 L 33 37 L 33 34"/>
<!-- handle (partially shown) -->
<path d="M 19 40 L 19 46 L 29 46 L 29 40"/>
<!-- cord wrapping -->
<path d="M 19 42 C 22 41, 26 42, 29 42"/>
<path d="M 19 44 C 22 43, 26 44, 29 44"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- paper sheet -->
<path d="M 5 6 C 18 5.2, 31 6.8, 43 6 L 43 43 C 30 43.8, 17 42.2, 5 43 Z"/>
<!-- grid lines -->
<path d="M 5 17 C 18 16.5, 31 17.5, 43 17"/>
<path d="M 5 28 C 18 27.5, 31 28.5, 43 28"/>
<path d="M 16 6 L 16 43"/>
<path d="M 31 6 L 31 43"/>
<!-- design arc -->
<path d="M 9 38 C 15 27, 23 18, 38 12"/>
<!-- radius line -->
<path d="M 9 38 L 38 12"/>
<!-- tick marks at endpoints -->
<path d="M 8 36 L 10 40"/>
<path d="M 36 10 L 40 14"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- body -->
<path d="M 4 14 C 16 13, 30 15, 44 14 L 44 33 C 30 34, 16 32, 4 33 Z"/>
<!-- destination sign -->
<path d="M 6 14 C 18 13.2, 30 14.8, 42 14 L 42 10 C 30 9.2, 18 10.8, 6 10 Z"/>
<!-- window strip -->
<path d="M 5 16 C 13 15.5, 21 16.5, 29 16 L 29 25 C 21 25.5, 13 24.5, 5 25 Z"/>
<!-- window dividers -->
<path d="M 13 16 L 13 25"/>
<path d="M 21 16 L 21 25"/>
<!-- door -->
<path d="M 32 16 L 32 33 L 42 33 L 42 16"/>
<path d="M 37 16 L 37 33"/>
<!-- wheels (semicircles) -->
<path d="M 7 33 A 5 5 0 0 0 17 33"/>
<path d="M 31 33 A 5 5 0 0 0 41 33"/>
</svg> <svg viewBox="0 0 48 48"
fill="none" stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
<!-- body -->
<path d="M 5 17 C 16 16.5, 31 17.5, 43 17 L 43 42 C 31 42.5, 16 41.5, 5 42 Z"/>
<!-- grip (left) -->
<path d="M 5 17 C 3 19, 3 33, 5 37"/>
<!-- shutter button (left of viewfinder) -->
<path d="M 11 17 C 11 13, 17 13, 17 17"/>
<!-- viewfinder hump (center, smaller) -->
<path d="M 19 17 L 19 12 C 19 11, 29 11, 29 12 L 29 17"/>
<!-- dials (right) -->
<path d="M 32 17 C 32 12, 38 12, 38 17"/>
<path d="M 39 17 C 39 14, 43 14, 43 17"/>
<!-- lens outer ring -->
<path d="M 21 20 C 28 20, 32 24, 32 29 C 32 34, 28 39, 21 39 C 14 39, 10 34, 10 29 C 10 24, 14 20, 21 20 Z"/>
<!-- lens inner ring -->
<path d="M 21 24 C 26 24, 28 27, 28 29 C 28 32, 26 35, 21 35 C 16 35, 14 32, 14 29 C 14 27, 16 24, 21 24 Z"/>
</svg>