Getting started
Basic structure
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
width="200"
height="200"
>
<circle cx="50" cy="50" r="40" fill="blue" stroke="black" stroke-width="2" />
</svg>
viewBox defines coordinate system: "min-x min-y width height"
Embedding in HTML
<!-- Inline (full CSS/JS access) -->
<svg>...</svg>
<!-- Image tag (no scripting) -->
<img src="image.svg" alt="..." />
<!-- CSS background -->
background-image: url('image.svg');
<!-- Object (scriptable) -->
<object data="image.svg" type="image/svg+xml"></object>
<!-- Data URI -->
<img src="data:image/svg+xml;utf8,<svg>...</svg>" />
preserveAspectRatio
| Value | Behavior |
|---|---|
xMidYMid meet |
Center, fit inside (default) |
xMidYMid slice |
Center, fill and crop |
xMinYMin meet |
Top-left, fit inside |
xMaxYMax meet |
Bottom-right, fit inside |
none |
Stretch to fill |
<svg preserveAspectRatio="xMidYMid slice">
<!-- ... -->
</svg>
Basic shapes
Rectangle
<rect x="10" y="10" width="80" height="60" />
<!-- Rounded corners -->
<rect x="10" y="10" width="80" height="60" rx="5" ry="5" />
Circle & ellipse
<!-- Circle -->
<circle cx="50" cy="50" r="40" />
<!-- Ellipse -->
<ellipse cx="50" cy="50" rx="40" ry="25" />
Lines & polygons
<!-- Line -->
<line x1="10" y1="10" x2="90" y2="90" />
<!-- Polyline (open) -->
<polyline points="10,10 50,50 90,10" />
<!-- Polygon (closed) -->
<polygon points="50,5 90,90 10,90" />
Path commands
Command reference
| Command | Params | Description |
|---|---|---|
M x y |
moveto | Move to point |
L x y |
lineto | Line to point |
H x |
horizontal | Horizontal line |
V y |
vertical | Vertical line |
C x1 y1, x2 y2, x y |
cubic bezier | Two control points |
S x2 y2, x y |
smooth cubic | Reflects previous control |
Q x1 y1, x y |
quadratic | One control point |
T x y |
smooth quadratic | Reflects previous |
A rx ry rot large sweep x y |
arc | Elliptical arc |
Z |
closepath | Close path |
Uppercase = absolute coordinates, lowercase = relative
Path examples
<!-- Triangle -->
<path d="M 50 5 L 90 90 L 10 90 Z" />
<!-- Bezier curve -->
<path d="M 10 80 C 40 10, 65 10, 95 80" />
<!-- Smooth curve -->
<path d="M 10 80 Q 95 10 180 80" />
<!-- Arc -->
<path d="M 10 50 A 40 40 0 1 1 90 50" />
Arc command details
<path
d="M x1 y1 A rx ry
x-rotation
large-arc-flag
sweep-flag
x2 y2"
/>
| Parameter | Values |
|---|---|
rx ry |
Ellipse radii |
x-rotation |
Degrees (0-360) |
large-arc-flag |
0 = small, 1 = large |
sweep-flag |
0 = CCW, 1 = CW |
Styling
Fill attributes
<rect fill="red" fill-opacity="0.5" fill-rule="evenodd" />
| Attribute | Values |
|---|---|
fill |
color, url(#id), none |
fill-opacity |
0-1 |
fill-rule |
nonzero, evenodd |
Stroke attributes
<line
stroke="blue"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
stroke-dasharray="5,3"
/>
| Attribute | Values |
|---|---|
stroke |
color, url(#id), none |
stroke-width |
number |
stroke-opacity |
0-1 |
stroke-linecap |
butt, round, square |
stroke-linejoin |
miter, round, bevel |
stroke-dasharray |
5,3 (dash, gap) |
stroke-dashoffset |
number |
Opacity
<!-- Global opacity -->
<rect opacity="0.5" />
<!-- Separate fill/stroke -->
<rect fill-opacity="0.8" stroke-opacity="0.3" />
Text
Basic text
<text
x="50"
y="50"
text-anchor="middle"
dominant-baseline="central"
font-family="Arial"
font-size="16"
fill="black"
>
Hello SVG
</text>
| Attribute | Values |
|---|---|
text-anchor |
start, middle, end |
dominant-baseline |
auto, central, hanging |
Multi-line text
<text>
<tspan x="10" dy="1.2em">Line 1</tspan>
<tspan x="10" dy="1.2em">Line 2</tspan>
<tspan x="10" dy="1.2em">Line 3</tspan>
</text>
dy = vertical offset from previous position
Text on path
<defs>
<path id="curve" d="M10,80 Q95,10 180,80" />
</defs>
<text>
<textPath href="#curve"> Text along a path </textPath>
</text>
Gradients
Linear gradient
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#000" />
<stop offset="50%" stop-color="#f00" />
<stop offset="100%" stop-color="#fff" />
</linearGradient>
</defs>
<rect fill="url(#grad1)" width="100" height="100" />
x1, y1, x2, y2 define gradient vector (direction)
Radial gradient
<defs>
<radialGradient id="grad2" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="white" />
<stop offset="100%" stop-color="blue" />
</radialGradient>
</defs>
<circle fill="url(#grad2)" cx="50" cy="50" r="40" />
Gradient options
<linearGradient gradientUnits="objectBoundingBox" spreadMethod="pad">
<!-- stops -->
</linearGradient>
| Attribute | Values |
|---|---|
gradientUnits |
objectBoundingBox, userSpaceOnUse |
spreadMethod |
pad, reflect, repeat |
Transforms
Transform functions
<rect transform="translate(50, 50)" />
<rect transform="rotate(45)" />
<rect transform="rotate(45, 50, 50)" />
<rect transform="scale(2)" />
<rect transform="scale(2, 0.5)" />
<rect transform="skewX(30)" />
<rect transform="skewY(15)" />
Chain transforms
<!-- Applied right-to-left -->
<rect transform="translate(50,50) rotate(45)" />
<!-- Equivalent to: -->
<!-- 1. rotate(45) -->
<!-- 2. translate(50,50) -->
Matrix transform
<rect transform="matrix(a, b, c, d, e, f)" />
Matrix: [a c e]
[b d f]
[0 0 1]
Groups & reuse
Groups
<g fill="red" opacity="0.5">
<rect x="10" y="10" width="30" height="30" />
<circle cx="70" cy="25" r="15" />
</g>
Groups inherit attributes to children
Symbols & use
<defs>
<symbol id="icon" viewBox="0 0 24 24">
<path d="M12 2 L22 22 L2 22 Z" />
</symbol>
</defs>
<use href="#icon" x="10" y="10" width="24" height="24" />
<use href="#icon" x="50" y="10" width="48" height="48" />
Defs for reusable elements
<defs>
<!-- Gradients -->
<linearGradient id="grad">...</linearGradient>
<!-- Patterns -->
<pattern id="pattern">...</pattern>
<!-- Clip paths -->
<clipPath id="clip">...</clipPath>
<!-- Filters -->
<filter id="blur">...</filter>
</defs>
Filters
Common filters
<defs>
<!-- Gaussian blur -->
<filter id="blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
</filter>
<!-- Drop shadow -->
<filter id="shadow">
<feDropShadow
dx="2"
dy="2"
stdDeviation="2"
flood-color="#000"
flood-opacity="0.5"
/>
</filter>
</defs>
<rect filter="url(#blur)" ... />
<circle filter="url(#shadow)" ... />
Filter primitives
| Primitive | Description |
|---|---|
feGaussianBlur |
Blur effect |
feDropShadow |
Drop shadow |
feColorMatrix |
Color transformation |
feBlend |
Blend modes |
feComposite |
Combine images |
feOffset |
Offset image |
feMerge |
Merge multiple inputs |
feFlood |
Solid color |
Complex filter
<filter id="complex">
<feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur" />
<feOffset in="blur" dx="4" dy="4" result="offsetBlur" />
<feMerge>
<feMergeNode in="offsetBlur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
Clipping & masking
Clip path
<defs>
<clipPath id="clip">
<circle cx="50" cy="50" r="40" />
</clipPath>
</defs>
<image clip-path="url(#clip)" href="photo.jpg" width="100" height="100" />
Clip path defines visible region (hard edges)
Mask
<defs>
<mask id="mask">
<rect width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="30" fill="black" />
</mask>
</defs>
<rect mask="url(#mask)" width="100" height="100" fill="blue" />
Mask uses alpha channel (soft edges)
Clip rule
<clipPath clip-rule="evenodd">
<!-- complex path -->
</clipPath>
| Value | Description |
|---|---|
nonzero |
Default winding rule |
evenodd |
Even-odd fill rule |
Markers
Arrow marker
<defs>
<marker
id="arrow"
viewBox="0 0 10 10"
refX="5"
refY="5"
markerWidth="6"
markerHeight="6"
orient="auto-start-reverse"
>
<path d="M 0 0 L 10 5 L 0 10 z" />
</marker>
</defs>
<line
x1="10"
y1="50"
x2="90"
y2="50"
marker-start="url(#arrow)"
marker-end="url(#arrow)"
/>
Marker attributes
| Attribute | Description |
|---|---|
marker-start |
Start of line |
marker-mid |
Middle vertices |
marker-end |
End of line |
orient |
auto, auto-start-reverse, angle |
Animations (SMIL)
Animate attribute
<circle cx="50" cy="50" r="10">
<animate
attributeName="r"
from="10"
to="40"
dur="1s"
repeatCount="indefinite"
/>
</circle>
Animate transform
<rect x="25" y="25" width="50" height="50">
<animateTransform
attributeName="transform"
type="rotate"
from="0 50 50"
to="360 50 50"
dur="2s"
repeatCount="indefinite"
/>
</rect>
Animate motion
<circle r="5" fill="red">
<animateMotion
dur="3s"
repeatCount="indefinite"
path="M10,80 Q95,10 180,80"
/>
</circle>
Animation attributes
| Attribute | Values |
|---|---|
dur |
1s, 500ms, 2.5s |
repeatCount |
number, indefinite |
fill |
freeze, remove |
calcMode |
linear, discrete, spline |
Patterns
Basic pattern
<defs>
<pattern
id="dots"
x="0"
y="0"
width="20"
height="20"
patternUnits="userSpaceOnUse"
>
<circle cx="10" cy="10" r="5" fill="blue" />
</pattern>
</defs>
<rect fill="url(#dots)" width="200" height="200" />
Pattern with transform
<pattern id="stripes" patternTransform="rotate(45)">
<rect width="4" height="10" fill="black" />
<rect x="4" width="6" height="10" fill="white" />
</pattern>
Advanced techniques
currentColor
<svg style="color: red;">
<circle fill="currentColor" ... />
<!-- Uses parent's color -->
</svg>
CSS styling
<style>
.my-shape {
fill: blue;
stroke: black;
stroke-width: 2;
}
.my-shape:hover {
fill: red;
}
</style>
<rect class="my-shape" ... />
JavaScript manipulation
<svg id="mySvg">
<circle id="myCircle" ... />
</svg>
<script>
const circle = document.getElementById("myCircle");
circle.setAttribute("r", "50");
circle.style.fill = "red";
</script>
Gotchas
Common issues
- ⚠️ viewBox vs dimensions:
viewBoxdefines coordinate system;width/heightdefine display size - ⚠️ Path case matters: Uppercase = absolute, lowercase = relative coordinates
- ⚠️ Arc complexity: Four possible arcs for same endpoints — understand flags
- ⚠️ Transform order: Applied right-to-left:
translate() rotate()≠rotate() translate() - ⚠️ Text doesn't wrap: Use
<tspan>withdyfor multi-line text - ⚠️ Gradient references: Must use
idandurl(#id)— inline values don't work - ⚠️ Fill rule: Default is
nonzero— complex paths may needevenodd - ⚠️ SMIL support: Works but CSS animations preferred for modern browsers
Best practices
- Use
<defs>for reusable elements - Prefer
<symbol>over<g>for icons - Optimize paths with SVGO
- Use
aria-labelfor accessibility - Minimize precision (2 decimals sufficient)
- Group related elements with
<g>
Also see
- MDN: SVG Reference (developer.mozilla.org)
- MDN: SVG Element Reference (developer.mozilla.org)
- MDN: SVG Attribute Reference (developer.mozilla.org)
- MDN: Paths Tutorial (developer.mozilla.org)
- W3C SVG2 Specification (w3.org)
- SVG Pocket Guide (svgpocketguide.com)