SVG 101
Your comprehensive guide to Scalable Vector Graphics. From basic shapes to complex paths and animations, learn how to create crisp, scalable images for the web.
Fundamentals
What is SVG?
SVG stands for Scalable Vector Graphics. Unlike raster images (JPEG, PNG) which are made of pixels, SVG is an XML-based format that defines images using lines, curves, and shapes. This means they can be scaled to any size without losing quality.
- Resolution Independent: Looks crisp on any screen density.
- Small File Size: Often smaller than equivalent bitmaps for simple graphics.
- Scriptable: Can be manipulated with CSS and JavaScript.
- Accessible: Text inside SVG is selectable and readable by screen readers.
Why SVG matters for the modern web?
The SVG Element & ViewBox
The <svg> tag is the container for your graphics. The viewBox attribute is arguably the most important concept to understand. It defines the coordinate system and aspect ratio.
viewBox="min-x min-y width height" defines the visible area of the infinite canvas.
<svg width="400" height="400" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" class="border border-dashed border-slate-300 bg-slate-50/50">
<!-- Grid lines for context -->
<defs>
<pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse">
<path d="M 10 0 L 0 0 0 10" fill="none" stroke="gray" stroke-width="0.5" opacity="0.2"/>
</pattern>
</defs>
<rect width="100" height="100" fill="url(#grid)" />
<!-- The coordinate system goes from 0,0 to 100,100 -->
<circle cx="50" cy="50" r="30" fill="#3b82f6" class="hover:fill-blue-600 transition-colors duration-300 cursor-pointer" />
<text x="50" y="90" font-size="8" text-anchor="middle" fill="#64748b">(50, 50)</text>
</svg>Basic Shapes
Rectangles & Circles
SVG provides primitives for common geometric shapes. Try hovering over them!
<svg width="400" height="200" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
<!-- Standard Rect with hover effect -->
<rect x="10" y="10" width="80" height="80" fill="#ef4444" class="transition-all duration-500 hover:rx-20 hover:fill-red-600 cursor-pointer" />
<!-- Rounded Rect with opacity hover -->
<rect x="110" y="10" width="80" height="80" rx="15" fill="#f97316" class="transition-opacity duration-300 hover:opacity-75 cursor-pointer" />
</svg><svg width="400" height="200" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
<!-- Circle that pulses on hover -->
<circle cx="50" cy="50" r="40" fill="#eab308" class="transition-all duration-500 hover:r-45 cursor-pointer" />
<!-- Ellipse that rotates on hover (via CSS group wrapper usually, but here via direct transform origin if supported or CSS) -->
<ellipse cx="150" cy="50" rx="40" ry="25" fill="#84cc16" class="hover:fill-lime-600 transition-colors cursor-pointer" />
</svg>Lines, Polylines & Polygons
<svg width="400" height="200" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
<style>
.dashed-line { animation: dash 1s linear infinite; }
@keyframes dash { to { stroke-dashoffset: -20; } }
</style>
<line x1="10" y1="50" x2="190" y2="50" stroke="currentColor" stroke-width="4" stroke-dasharray="10, 10" class="dashed-line text-indigo-500" />
</svg><svg width="400" height="200" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
<!-- Polyline: Zigzag -->
<polyline points="10,50 30,20 50,80 70,20 90,50" fill="none" stroke="#06b6d4" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" />
<!-- Polygon: Star Shape -->
<polygon points="150,10 162,35 190,35 168,52 176,80 150,62 124,80 132,52 110,35 138,35" fill="#8b5cf6" class="hover:rotate-12 transition-transform origin-center duration-300 cursor-pointer" style="transform-origin: 150px 45px;" />
</svg>The Path
The Path Element
The <path> element can create any shape. It's powerful!
- M / m: Move to (x, y)
- L / l: Line to (x, y)
- H / h: Horizontal line to (x)
- V / v: Vertical line to (y)
- Z / z: Close path
- C / c: Cubic Bezier
- Q / q: Quadratic Bezier
- A / a: Arc
- S / s: Smooth Cubic
- T / t: Smooth Quadratic
<svg width="400" height="400" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="M50 30 C 40 10, 10 10, 10 40 C 10 70, 50 90, 50 90 C 50 90, 90 70, 90 40 C 90 10, 60 10, 50 30 Z"
fill="#ec4899"
stroke="#be185d"
stroke-width="2"
class="transition-transform duration-300 hover:scale-110 origin-center cursor-pointer"
style="transform-origin: 50px 50px;"
/>
</svg><svg width="400" height="200" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
<!-- Quadratic Curve -->
<path d="M 20 80 Q 100 10 180 80" fill="none" stroke="#14b8a6" stroke-width="4" stroke-linecap="round" />
<!-- Control Point Visualization -->
<line x1="20" y1="80" x2="100" y2="10" stroke="gray" stroke-width="1" stroke-dasharray="4" opacity="0.5" />
<line x1="180" y1="80" x2="100" y2="10" stroke="gray" stroke-width="1" stroke-dasharray="4" opacity="0.5" />
<circle cx="100" cy="10" r="4" fill="#ef4444" class="cursor-help">
<title>Control Point</title>
</circle>
<text x="100" y="25" text-anchor="middle" font-size="10" fill="gray">Control Point</text>
</svg>Styling & Transforms
Grouping & Transformations
<svg width="400" height="400" viewBox="-100 -100 200 200" xmlns="http://www.w3.org/2000/svg">
<!-- Sun -->
<circle r="20" fill="#fbbf24" />
<!-- Orbit Path -->
<circle r="70" fill="none" stroke="gray" opacity="0.3" />
<!-- Planet Group: Rotated 45 degrees -->
<g transform="rotate(45)">
<!-- Planet moved out to orbit radius -->
<circle cx="70" cy="0" r="10" fill="#3b82f6">
<animateTransform attributeName="transform" type="rotate" from="0 -70 0" to="360 -70 0" dur="4s" repeatCount="indefinite" />
</circle>
</g>
<!-- Another Planet -->
<g>
<circle cx="40" cy="0" r="6" fill="#10b981">
<animateTransform attributeName="transform" type="rotate" from="0 0 0" to="360 0 0" dur="3s" repeatCount="indefinite" />
</circle>
</g>
</svg>Advanced
Defs & Gradients
<svg width="400" height="200" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="sunset" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#fbbf24;stop-opacity:1" />
<stop offset="50%" style="stop-color:#f59e0b;stop-opacity:1" />
<stop offset="100%" style="stop-color:#ea580c;stop-opacity:1" />
</linearGradient>
<filter id="glow">
<feGaussianBlur stdDeviation="2.5" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<circle id="orb" r="15" />
</defs>
<rect width="200" height="100" fill="#1e293b" rx="8" />
<use href="#orb" x="50" y="50" fill="url(#sunset)" filter="url(#glow)" />
<use href="#orb" x="100" y="50" fill="url(#sunset)" filter="url(#glow)" style="opacity: 0.7" />
<use href="#orb" x="150" y="50" fill="url(#sunset)" filter="url(#glow)" style="opacity: 0.4" />
</svg>Text Paths
<svg width="400" height="200" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
<path id="wave" d="M 10 50 Q 55 10 100 50 T 190 50" fill="none" stroke="#cbd5e1" stroke-dasharray="4" />
<text font-family="monospace" font-size="14" fill="#475569">
<textPath href="#wave" startOffset="50%" text-anchor="middle">
Riding the SVG wave 🌊
</textPath>
</text>
</svg>