Chapter 15: SVG marker
SVG: markers
Imagine you’re drawing a map, a flowchart, a graph, or just a fancy arrow — and you want nice arrowheads, dots, diamonds, or custom shapes automatically placed at the start, middle, or end of lines and paths. Doing this manually with many <polygon> or <circle> elements would be painful and hard to maintain.
SVG markers solve exactly this problem — they let you define a small reusable graphic once, and then tell any <line>, <polyline>, or <path> to “put this marker on my ends (or even along the whole path)”.
I’m going to explain it like we’re sitting together building arrows step by step — slowly, clearly, with examples you can copy-paste right now.
What is an SVG <marker>?
- <marker> is a definition element — it lives inside <defs> (like <clipPath>, <pattern>, <filter>)
- It defines a small independent drawing area (like a mini-SVG inside your SVG)
- You give it an id
- Then you attach it to lines/paths using special attributes: marker-start, marker-mid, marker-end
Once attached, the marker automatically:
- Rotates to match the direction of the line/path
- Scales if needed
- Positions itself correctly at the exact endpoint (or midpoints)
Core attributes on <marker>
| Attribute | Meaning / Purpose | Common values | Default | Very important? |
|---|---|---|---|---|
| id | Unique name so you can reference it | “arrow”, “dot”, “myMarker” | — | ★★★★★ |
| markerWidth / markerHeight | Size of the marker’s viewport (like viewBox size) | 10, 12, 20, etc. | 3 | ★★★★★ |
| refX / refY | Which point inside marker is “pinned” to the line end | 0–markerWidth, usually center or tip | 0 | ★★★★★ |
| orient | How to rotate the marker | “auto” (follows line), angle in deg, “auto-start-reverse” | “auto” | ★★★★☆ |
| markerUnits | What units for width/height/refX/refY | “userSpaceOnUse” or “strokeWidth” | “strokeWidth” | ★★★☆☆ |
Most common & important combo (arrow tip):
|
0 1 2 3 4 5 6 7 8 |
markerWidth="10" markerHeight="10" refX="10" refY="5" ← tip of arrow is at (10,5) inside marker orient="auto" |
Here are some visual explanations of refX/refY and orient (very helpful to see where the “pin” point is):
(Imagine seeing here: diagram showing arrow marker with refX=10 refY=5 pointing exactly at line end + rotation arrows)
Example 1 – Classic arrowhead on both ends
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<svg width="500" height="180" style="border:1px solid #eee; background:#f9f9f9;"> <defs> <marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto"> <path d="M0,0 L0,12 L12,6 Z" fill="#FF5722" stroke="#B71C1C" stroke-width="1"/> </marker> </defs> <line x1="60" y1="90" x2="440" y2="90" stroke="#2196F3" stroke-width="6" marker-start="url(#arrow)" marker-end="url(#arrow)" /> </svg> |
Result: Blue line with orange arrowheads on both ends, automatically rotated.
Example 2 – Different marker for start & end (very common pattern)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<svg width="400" height="220"> <defs> <!-- Start: small circle --> <marker id="startDot" markerWidth="8" markerHeight="8" refX="4" refY="4"> <circle cx="4" cy="4" r="3.5" fill="#4CAF50"/> </marker> <!-- End: arrow --> <marker id="endArrow" markerWidth="12" markerHeight="12" refX="11" refY="6" orient="auto"> <polygon points="0,0 0,12 11,6" fill="#F44336"/> </marker> </defs> <polyline points="40,100 140,40 240,120 340,60" fill="none" stroke="#673AB7" stroke-width="5" marker-start="url(#startDot)" marker-end="url(#endArrow)"/> </svg> |
Example 3 – Markers along the whole path (marker-mid)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<svg width="500" height="200"> <defs> <marker id="midDot" markerWidth="6" markerHeight="6" refX="3" refY="3"> <circle cx="3" cy="3" r="2.5" fill="#FF9800"/> </marker> </defs> <path d="M 40 100 Q 150 30, 250 100 T 460 100" fill="none" stroke="#009688" stroke-width="8" marker-mid="url(#midDot)" marker-start="url(#midDot)" marker-end="url(#midDot)"/> </svg> |
→ Dots appear at start, end, and every sharp corner (where direction changes)
Example 4 – Custom size with strokeWidth units (very useful for consistent look)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<svg width="400" height="140"> <defs> <marker id="bigArrow" markerWidth="16" markerHeight="16" refX="14" refY="8" orient="auto" markerUnits="strokeWidth"> <path d="M0,0 L0,16 L16,8 Z" fill="currentColor"/> </marker> </defs> <line x1="40" y1="40" x2="360" y2="40" stroke="purple" stroke-width="4" marker-end="url(#bigArrow)"/> <line x1="40" y1="100" x2="360" y2="100" stroke="purple" stroke-width="12" marker-end="url(#bigArrow)"/> </svg> |
→ Arrow scales with stroke-width — stays proportional (very clean look)
Quick Cheat Sheet – When to use which marker placement
| Attribute | Places marker at… | Typical use case |
|---|---|---|
| marker-start | Beginning of path (first point) | Starting dot, open arrow |
| marker-end | End of path (last point) | Arrowhead, destination marker |
| marker-mid | Every vertex (corner/point) except start & end | Mid dots, vertices in graphs, dashed styles |
| All three | Start + mid + end | Full control |
Common beginner mistakes
- Forget to put <marker> inside <defs> → nothing shows
- Wrong refX/refY → arrow tip not touching line end (most common!)
- orient=”0″ instead of “auto” → arrows don’t rotate with line direction
- markerUnits=”userSpaceOnUse” but forget to scale → markers too big/small
- Using fill=”none” on marker path → invisible
- Referencing wrong id (url(#arrow) vs url(#Arrow) — case sensitive!)
Mini practice challenges
- Make a red dashed line with small black circles at both ends and mid points
- Create a green flowchart-style arrow with a bigger triangle head and a small square start marker
- Draw a curved path (use Q or C) with orange diamonds at every corner
Paste your code here if you want — I’ll review it like we’re pair-programming together 😄
Any part still fuzzy? refX/refY positioning? orient=”auto” vs fixed angle? marker-mid behavior? Scaling with stroke-width? Just say the word — we’ll redraw examples bigger/slower until it clicks perfectly! 🚀
