SVG Drawing Guide
A complete reference and methodology for hand-crafting SVG (Scalable Vector Graphics) code. Use this skill whenever you need to create or modify SVG files directly in code — icons, favicons, illustrations, badges, diagrams, or any vector graphic.
When to Use This Skill
-
User asks to create/draw/design an SVG icon, favicon, logo, badge, illustration
-
User asks to modify or fix an existing SVG file
-
User needs an SVG element for a web component (spinner, decorative shape, etc.)
-
User wants to understand SVG syntax or debug SVG code
- SVG Fundamentals
The <svg> Root Element
Every SVG starts with the <svg> element. Always include xmlns for standalone files:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100"> <!-- content --> </svg>
Key attributes:
-
xmlns="http://www.w3.org/2000/svg" — required for standalone .svg files, optional when inlined in HTML
-
viewBox="minX minY width height" — defines the internal coordinate system (ALWAYS use this)
-
width / height — sets the rendered size in the DOM (can also be controlled via CSS)
The viewBox — Most Important Concept
The viewBox creates an internal coordinate system independent of the SVG's rendered size. This is what makes SVGs truly scalable.
<!-- This SVG will scale to any size while keeping proportions --> <svg viewBox="0 0 200 200"> <circle cx="100" cy="100" r="80" /> </svg>
How viewBox works:
-
viewBox="0 0 200 200" means: "My internal canvas goes from (0,0) to (200,200)"
-
All child elements use this coordinate system
-
The SVG scales to fit its container while preserving the viewBox aspect ratio
-
Changing the first two values pans the view; changing the last two zooms in/out
Common viewBox patterns:
viewBox="0 0 24 24" <!-- Standard icon size (Material, Lucide, etc.) --> viewBox="0 0 32 32" <!-- Favicon-sized --> viewBox="0 0 100 100" <!-- Easy percentage-like coordinates --> viewBox="0 0 200 60" <!-- Horizontal logo lockup -->
Rule: Always define a viewBox . Without it, the SVG uses raw pixel coordinates and won't scale.
Coordinate System
-
Origin (0, 0) is the top-left corner
-
X increases to the right, Y increases downward (opposite of math convention)
-
All units are unitless within viewBox — they map proportionally to rendered size
- Basic Shape Elements
<line>
Draws a straight line between two points.
<line x1="10" y1="10" x2="90" y2="90" stroke="#34D399" stroke-width="3" />
Attribute Description
x1 , y1
Start point
x2 , y2
End point
stroke
Line color (required — lines are invisible without it)
stroke-width
Line thickness
<rect>
Draws a rectangle.
<rect x="10" y="10" width="80" height="60" rx="8" ry="8" fill="#4F46E5" />
Attribute Description
x , y
Top-left corner position
width , height
Dimensions
rx , ry
Corner radius (like border-radius ). If only rx is set, ry defaults to the same value
fill
Fill color
<circle>
Draws a circle.
<circle cx="50" cy="50" r="40" fill="#06B6D4" />
Attribute Description
cx , cy
Center point
r
Radius (shape disappears if r="0" )
<ellipse>
Like <circle> but with independent horizontal and vertical radii.
<ellipse cx="50" cy="50" rx="40" ry="25" fill="#8B5CF6" />
Attribute Description
cx , cy
Center point
rx
Horizontal radius
ry
Vertical radius
<polygon>
A closed shape defined by a set of points. The browser automatically connects the last point back to the first.
<polygon points="50,5 95,27.5 95,72.5 50,95 5,72.5 5,27.5" fill="#10B981" />
Tip: Use commas and newlines for readability — they're valid SVG:
<polygon points=" 50,5 95,27.5 95,72.5 50,95 5,72.5 5,27.5 " />
<polyline>
Like <polygon> but does NOT auto-close. Good for open shapes (charts, graphs).
<polyline points="10,90 30,40 50,70 70,20 90,60" fill="none" stroke="#F59E0B" stroke-width="2" />
<text>
Renders text inside SVG. Positioning is from the baseline.
<text x="50" y="50" font-family="Georgia, serif" font-size="24" fill="white" text-anchor="middle"> Hello </text>
Attribute Description
x , y
Position (baseline origin)
text-anchor
Horizontal alignment: start , middle , end
dominant-baseline
Vertical alignment: auto , middle , hanging
font-family
Font (use web-safe fonts in standalone SVGs)
font-size
Size in viewBox units
font-weight
Weight: normal , bold , 100 -900
font-style
normal or italic
Centering text perfectly:
<text x="50" y="50" text-anchor="middle" dominant-baseline="central" font-size="16"> Centered </text>
- The <path> Element — The Most Powerful Shape
The <path> element can draw anything. It uses a mini-language of commands in its d attribute.
Path Commands Reference
All commands have uppercase (absolute coordinates) and lowercase (relative coordinates) variants.
Command Name Parameters Description
M / m
MoveTo x y
Move pen to point (no drawing)
L / l
LineTo x y
Draw line to point
H / h
Horizontal LineTo x
Draw horizontal line
V / v
Vertical LineTo y
Draw vertical line
C / c
Cubic Bezier x1 y1 x2 y2 x y
Curve with 2 control points
S / s
Smooth Cubic x2 y2 x y
Smooth continuation of cubic curve
Q / q
Quadratic Bezier x1 y1 x y
Curve with 1 control point
T / t
Smooth Quadratic x y
Smooth continuation of quadratic curve
A / a
Elliptical Arc rx ry rotation large-arc sweep x y
Arc segment
Z / z
ClosePath (none) Close path back to last M
Path Examples
Triangle:
<path d="M 50 10 L 90 90 L 10 90 Z" fill="#34D399" />
Rounded square (using curves):
<path d="M 20 8 H 80 Q 92 8 92 20 V 80 Q 92 92 80 92 H 20 Q 8 92 8 80 V 20 Q 8 8 20 8 Z" fill="#1E1B4B" />
Sigma symbol (Σ):
<path d="M 28 26 L 62 26 L 46 50 L 62 74 L 28 74" fill="none" stroke="#34D399" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" />
Heart shape:
<path d="M 50 30 Q 50 10 30 10 Q 10 10 10 30 Q 10 50 50 80 Q 90 50 90 30 Q 90 10 70 10 Q 50 10 50 30 Z" fill="#EF4444" />
Understanding Bezier Curves
Cubic Bezier (C ) — Two control points for complex curves:
C x1 y1, x2 y2, endX endY ^ ^ ^ | | └── end point | └── control point 2 (influences end) └── control point 1 (influences start)
Quadratic Bezier (Q ) — One control point for simpler curves:
Q controlX controlY, endX endY
Smooth variants (S , T ) mirror the previous control point automatically, creating smooth continuations.
Elliptical Arc (A )
The most complex command. Parameters:
A rx ry x-rotation large-arc-flag sweep-flag x y
-
rx , ry — radii of the ellipse
-
x-rotation — rotation of the ellipse in degrees
-
large-arc-flag — 0 for minor arc, 1 for major arc
-
sweep-flag — 0 for counter-clockwise, 1 for clockwise
-
x , y — end point
Semicircle:
<path d="M 10 50 A 40 40 0 0 1 90 50" fill="none" stroke="#06B6D4" stroke-width="3" />
- Presentational Attributes (Fill & Stroke)
Fill
Attribute Description
fill
Fill color. Any CSS color value, url(#gradientId) , or none
fill-opacity
Opacity of the fill (0 to 1)
fill-rule
nonzero (default) or evenodd — determines inside/outside for complex paths
Stroke
Attribute Description
stroke
Stroke color
stroke-width
Width of the stroke
stroke-opacity
Opacity of the stroke (0 to 1)
stroke-linecap
End shape: butt (default), round , square
stroke-linejoin
Corner shape: miter (default), round , bevel
stroke-dasharray
Dash pattern (e.g., "10 5" = 10px dash, 5px gap)
stroke-dashoffset
Offset for the dash pattern start
Important: Stroke is drawn on the center of the path, not inside or outside. A stroke-width="10" extends 5px inward and 5px outward from the path.
Opacity
Attribute Description
opacity
Overall element opacity (affects both fill and stroke)
fill-opacity
Just fill opacity
stroke-opacity
Just stroke opacity
All presentational attributes can also be set in CSS:
<style> .accent { fill: #34D399; stroke: #06B6D4; stroke-width: 2; } </style> <circle class="accent" cx="50" cy="50" r="30" />
- The <defs> Element and Reusable Definitions
The <defs> element contains definitions that are not rendered directly but can be referenced by other elements. Always put gradients, filters, clip paths, and patterns inside <defs> .
<svg viewBox="0 0 100 100"> <defs> <!-- Definitions go here — not rendered directly --> <linearGradient id="myGrad">...</linearGradient> <filter id="myFilter">...</filter> <clipPath id="myClip">...</clipPath> </defs>
<!-- Elements that use the definitions --> <rect fill="url(#myGrad)" filter="url(#myFilter)" clip-path="url(#myClip)" ... /> </svg>
- Gradients
Linear Gradient
Goes in a straight line from one color to another.
<defs> <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" stop-color="#34D399" /> <stop offset="50%" stop-color="#06B6D4" /> <stop offset="100%" stop-color="#8B5CF6" /> </linearGradient> </defs> <rect fill="url(#grad1)" x="0" y="0" width="100" height="100" />
Direction control via x1/y1/x2/y2:
-
x1="0%" x2="100%" y1="0%" y2="0%" — horizontal (left to right) [default]
-
x1="0%" x2="0%" y1="0%" y2="100%" — vertical (top to bottom)
-
x1="0%" x2="100%" y1="0%" y2="100%" — diagonal (top-left to bottom-right)
Stop attributes:
-
offset — position along the gradient (0% to 100%)
-
stop-color — color at this stop
-
stop-opacity — opacity at this stop (0 to 1)
Radial Gradient
Radiates outward from a center point.
<defs> <radialGradient id="grad2" cx="50%" cy="50%" r="50%"> <stop offset="0%" stop-color="#FFFFFF" stop-opacity="0.8" /> <stop offset="100%" stop-color="#34D399" stop-opacity="0" /> </radialGradient> </defs> <circle fill="url(#grad2)" cx="50" cy="50" r="40" />
Attributes:
-
cx , cy — center of the gradient
-
r — radius
-
fx , fy — focal point (where the gradient appears to originate from, defaults to cx/cy)
- Filters
SVG filters apply visual effects (blur, shadow, glow, etc.). Defined in <defs> , referenced via filter="url(#id)" .
Gaussian Blur
<defs> <filter id="blur1"> <feGaussianBlur in="SourceGraphic" stdDeviation="3" /> </filter> </defs> <circle filter="url(#blur1)" cx="50" cy="50" r="30" fill="#34D399" />
Drop Shadow
<defs> <filter id="shadow1" x="-20%" y="-20%" width="140%" height="140%"> <feDropShadow dx="2" dy="4" stdDeviation="3" flood-color="#000000" flood-opacity="0.3" /> </filter> </defs>
Glow Effect
<defs> <filter id="glow1" x="-50%" y="-50%" width="200%" height="200%"> <feGaussianBlur in="SourceGraphic" stdDeviation="4" result="blur" /> <feMerge> <feMergeNode in="blur" /> <feMergeNode in="SourceGraphic" /> </feMerge> </filter> </defs>
Common Filter Primitives
Element Effect
<feGaussianBlur>
Blur
<feDropShadow>
Drop shadow (shorthand)
<feOffset>
Offset position
<feFlood>
Fill with a color
<feComposite>
Combine two images
<feMerge>
Layer multiple results
<feColorMatrix>
Color manipulation
<feMorphology>
Erode or dilate
Tip: Expand the x , y , width , height attributes on <filter> to prevent clipping of effects that extend beyond the element bounds (blur, glow, shadow).
- Transforms
Apply geometric transformations to elements or groups.
<rect transform="translate(10, 20) rotate(45, 50, 50) scale(1.5)" ... />
Transform Functions
Function Syntax Description
translate
translate(tx, ty)
Move element
rotate
rotate(angle, cx, cy)
Rotate around point (cx,cy). Without cx/cy rotates around origin (0,0)
scale
scale(sx, sy)
Scale. Single value scales uniformly
skewX
skewX(angle)
Skew along X axis
skewY
skewY(angle)
Skew along Y axis
matrix
matrix(a,b,c,d,e,f)
Full 2D transformation matrix
Important: rotate(45) rotates around the SVG origin (0,0), not the element center. To rotate around the element's center, use rotate(45, cx, cy) where cx/cy is the center of the element.
- Grouping and Organization
<g> — Group Element
Groups elements together. Transforms and styles applied to <g> affect all children.
<g transform="translate(50, 50)" opacity="0.8"> <circle cx="0" cy="0" r="20" fill="#34D399" /> <circle cx="30" cy="0" r="15" fill="#06B6D4" /> </g>
<use> — Reuse Elements
Reference a defined element multiple times:
<defs> <circle id="dot" r="5" fill="#34D399" /> </defs> <use href="#dot" x="20" y="20" /> <use href="#dot" x="50" y="50" /> <use href="#dot" x="80" y="80" />
<clipPath> — Clip to a Shape
<defs> <clipPath id="circleClip"> <circle cx="50" cy="50" r="40" /> </clipPath> </defs> <rect clip-path="url(#circleClip)" x="0" y="0" width="100" height="100" fill="#4F46E5" />
<mask> — Soft Masking with Opacity
<defs> <mask id="fadeMask"> <rect x="0" y="0" width="100" height="100" fill="white" /> <circle cx="50" cy="50" r="30" fill="black" /> </mask> </defs> <rect mask="url(#fadeMask)" x="0" y="0" width="100" height="100" fill="#34D399" />
White areas in the mask are visible, black areas are hidden, gray values create partial transparency.
- Accessibility
Always add accessibility attributes to meaningful SVGs:
<svg role="img" aria-labelledby="title desc" viewBox="0 0 100 100"> <title id="title">Icon Name</title> <desc id="desc">A brief description of what this SVG depicts</desc> <!-- content --> </svg>
For decorative SVGs (not conveying information):
<svg aria-hidden="true" viewBox="0 0 100 100"> <!-- decorative content --> </svg>
- CSS Styling in SVG
SVG attributes can be set via CSS. Use <style> inside the SVG or external stylesheets:
<svg viewBox="0 0 100 100"> <style> .node { fill: #34D399; transition: r 300ms ease; } .node:hover { r: 15; fill: #06B6D4; } .link { stroke: #34D399; stroke-width: 2; opacity: 0.6; } </style> <line class="link" x1="20" y1="20" x2="80" y2="80" /> <circle class="node" cx="20" cy="20" r="10" /> <circle class="node" cx="80" cy="80" r="10" /> </svg>
CSS-animatable SVG properties: fill , stroke , stroke-width , stroke-dasharray , stroke-dashoffset , opacity , r , cx , cy , x , y , width , height .
CSS Animations for SVG
Dash animation (self-drawing effect):
<style> @keyframes draw { from { stroke-dashoffset: 763; } to { stroke-dashoffset: 0; } } .draw-path { stroke-dasharray: 763; stroke-dashoffset: 763; animation: draw 2s ease forwards; } </style>
Spinner:
<style> @keyframes spin { to { transform: rotate(360deg); } } .spinner { animation: spin 1s linear infinite; transform-origin: center; } </style>
- Favicon & Icon Best Practices
Favicon Requirements
Standard .ico contains multiple sizes: 16x16, 32x32, 48x48, 256x256.
Modern browsers also accept SVG favicons:
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
Design Rules for Small Sizes
-
Simplicity is king — At 16x16, fine details vanish. Use bold, simple shapes.
-
Max 2-3 visual elements — One primary shape + one accent.
-
Strong silhouette — The icon should be recognizable as a solid silhouette.
-
High contrast — Ensure strong contrast between foreground and background.
-
Thick strokes — Minimum stroke-width of 2-3 in a 32x32 viewBox.
-
No text — Letters are illegible at 16px (a single symbol like Σ is OK).
-
Test at actual size — View your SVG at 16x16 and 32x32 pixels before finalizing.
Icon Template
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"> <defs> <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" stop-color="#1E1B4B" /> <stop offset="100%" stop-color="#312E81" /> </linearGradient> </defs>
<!-- Background with rounded corners --> <rect width="32" height="32" rx="7" fill="url(#bg)" />
<!-- Main symbol here --> </svg>
- Optimization Checklist
Before delivering an SVG:
-
Has viewBox — Always present for scalability
-
No unnecessary attributes — Remove defaults (fill-rule="nonzero" , stroke="none" when no stroke)
-
Grouped logically — Use <g> with meaningful structure
-
Gradients/filters in <defs> — Never define them inline
-
Unique IDs — All id attributes must be unique within the document (critical when multiple SVGs are on the same page)
-
Minimal decimal precision — Round to 1-2 decimal places (50.5 , not 50.123456 )
-
Readable formatting — Use commas and newlines for complex points and d attributes
-
Accessible — role="img"
- <title> for meaningful SVGs, aria-hidden="true" for decorative ones
-
No invisible elements — Remove shapes with opacity="0" or outside the viewBox
-
Colors use consistent format — Pick one format (hex, oklch, hsl) and use it throughout
- Common Patterns & Recipes
Rounded Square Background (for icons)
<rect width="100" height="100" rx="22" fill="#1E1B4B" />
Glowing Node (AI/tech aesthetic)
<circle cx="50" cy="50" r="8" fill="#34D399" opacity="0.2" /> <circle cx="50" cy="50" r="4" fill="#34D399" />
Neural Network Connection
<line x1="20" y1="20" x2="80" y2="80" stroke="#06B6D4" stroke-width="2" opacity="0.6" /> <circle cx="20" cy="20" r="5" fill="#34D399" /> <circle cx="80" cy="80" r="5" fill="#06B6D4" />
Circuit Trace
<line x1="60" y1="30" x2="85" y2="30" stroke="#06B6D4" stroke-width="2" opacity="0.7" /> <circle cx="85" cy="30" r="4" fill="#06B6D4" opacity="0.8" />
Gradient Text (via clip-path)
<defs> <linearGradient id="textGrad" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" stop-color="#65F2BE" /> <stop offset="50%" stop-color="#35C9FF" /> <stop offset="100%" stop-color="#9EFF8F" /> </linearGradient> </defs> <text fill="url(#textGrad)" font-size="24" font-weight="bold" x="50" y="55" text-anchor="middle"> TexAI </text>
Star / Sparkle (4-pointed)
<path d="M 50 35 L 53 47 L 65 50 L 53 53 L 50 65 L 47 53 L 35 50 L 47 47 Z" fill="#FFFFFF" />
Hexagon
<polygon points="50,5 95,27.5 95,72.5 50,95 5,72.5 5,27.5" fill="#4F46E5" />
- Workflow for Creating SVGs
Step 1: Define the Canvas
Choose a viewBox appropriate for the use case:
-
Icons: 0 0 24 24 or 0 0 32 32
-
Logos: 0 0 200 60 (horizontal) or 0 0 100 100 (square)
-
Illustrations: 0 0 400 300 or whatever fits the content
Step 2: Sketch the Composition
Plan which elements go where. Think in terms of:
-
Background shape (rounded rect, circle)
-
Primary element (the main symbol)
-
Secondary elements (accents, decorations)
Step 3: Build Layer by Layer
SVG renders in document order — later elements render on top of earlier ones:
<svg viewBox="0 0 100 100"> <!-- Layer 1: Background (renders first, at the back) --> <rect width="100" height="100" rx="20" fill="#1E1B4B" />
<!-- Layer 2: Main symbol (renders on top of background) --> <path d="..." fill="#34D399" />
<!-- Layer 3: Accents (renders on top of everything) --> <circle cx="75" cy="25" r="5" fill="#06B6D4" /> </svg>
Step 4: Add Polish
-
Gradients for depth
-
Opacity variations for hierarchy
-
Subtle glow filters for premium feel
-
Consistent stroke-width across all strokes
Step 5: Test and Optimize
-
View at target sizes (16px, 32px, 64px for favicons)
-
Check on both light and dark backgrounds
-
Validate that all IDs are unique
-
Remove unnecessary attributes
Sources
Knowledge synthesized from:
-
Josh W Comeau — A Friendly Introduction to SVG
-
W3Schools — SVG Tutorial (paths, gradients, strokes, filters, transforms)
-
MDN Web Docs — SVG Reference