← Back to the SVG Lab
Lesson

SVG & SVG Animation, Visually

SVG draws shapes with math, not pixels — so it stays razor-sharp at any size, weighs almost nothing, and can be styled and animated with CSS. This lesson covers the coordinate system, shapes, paths, gradients, and three ways to bring SVG to life, with live, editable-looking demos throughout.

Step 1

What SVG is — and why it's special

SVG (Scalable Vector Graphics) describes images as shapes and coordinates in XML, instead of a grid of pixels like a JPG or PNG. Because it's math, it scales to any size with zero blur, the file is tiny, and every shape is a real DOM element you can style, script, and animate.

Three ways to put SVG on a page

MethodLooks likeUse when
Inline<svg>…</svg> right in the HTMLYou want to style/animate the shapes with CSS & JS.
As an image<img src="logo.svg">A static logo or icon; no internal styling needed.
CSS backgroundbackground: url(bg.svg)Decorative patterns & backgrounds.
Inline is where the magic is. When SVG lives in your HTML, its shapes are DOM nodes — so CSS hovers, transitions, keyframes, and JavaScript all work on them, exactly like any other element.
Step 2

The canvas: viewBox & coordinates

Every SVG has an internal coordinate system set by viewBox="minX minY width height". Coordinates start at (0,0) top-left, x grows right, y grows down. Crucially, this is separate from the rendered pixel size — a 0 0 100 100 viewBox can display at any size and stay sharp.

<svg viewBox="0 0 100 100" width="200">
  <!-- a circle at the center, no matter the display size -->
  <circle cx="50" cy="50" r="40"/>
</svg>
Think of viewBox as the graph paper you draw on, and width/CSS as the size of the printout. Design once in viewBox units; let it render at any pixel size. This is why SVG is resolution-independent.
Step 3

Basic shapes

SVG ships with a small kit of primitive shapes, each a tag with coordinate attributes:

<rect>   <circle>   <ellipse>   <line>
<rect x="10" y="20" width="60" height="50" rx="8"/>   rounded corners via rx
<circle cx="120" cy="45" r="28"/>            center x/y + radius
<ellipse cx="200" cy="45" rx="34" ry="22"/>
<line x1="260" y1="20" x2="310" y2="70"/>
There's also <polygon> (a closed shape from a list of points) and <polyline> (the same, left open) — handy for arrows, stars, and simple charts.
Step 4

Paths: draw anything

The <path> element can draw any shape via a single d attribute — a string of drawing commands. Uppercase commands use absolute coordinates, lowercase use relative.

CommandMeans
M x yMove the pen to a point (no line drawn).
L x yLine to a point.
C …Cubic Bézier curve (two control points).
Q …Quadratic curve (one control point).
ZClose the path back to the start.
one <path> · M move · C curve · Z close
You rarely hand-write paths. Real path data comes from design tools (Figma, Illustrator) or icon sets — you just copy the d string. Knowing the commands lets you read and tweak them.
Step 5

Fill & stroke

Shapes have two paint properties: fill (the inside) and stroke (the outline). Stroke has its own modifiers — width, line caps, and joins.

fill only · stroke only (fill:none) · both + dashes
<circle fill="none" stroke="#7c3aed" stroke-width="6"
        stroke-linecap="round" stroke-dasharray="8 6"/>
These are presentation attributes — you can set them right on the element or in CSS (fill: #d97706). CSS wins, which is what makes hover and animation possible (Step 7).
Step 6

Gradients & <defs>

Gradients are defined once inside <defs> with an id, then referenced by any shape via fill="url(#id)". Change the definition once and every shape using it updates.

linearGradient   ·   radialGradient
<defs>
  <linearGradient id="lg" x1="0" y1="0" x2="1" y2="1">
    <stop offset="0%" stop-color="#f59e0b"/>
    <stop offset="100%" stop-color="#e11d48"/>
  </linearGradient>
</defs>
<rect fill="url(#lg)"/>
<defs> is also where you put reusable bits like filters (drop shadows, blur), clip paths, and patterns — define once, reference by id anywhere.
Step 7

Styling & hover with CSS

Inline SVG shapes obey CSS like any element. You can transition fill, stroke, opacity, and transform on :hover — the foundation of interactive icons and diagrams. Hover the circle:

:hover → fill changes & it scales up
circle { fill: #d97706; transition: fill .3s, transform .3s;
         transform-origin: center; transform-box: fill-box; }
circle:hover { fill: #7c3aed; transform: scale(1.25); }
Gotcha: to scale/rotate an SVG shape from its own center, set transform-box: fill-box and transform-origin: center. Without them, SVG transforms pivot around the viewBox's (0,0), not the shape.
Step 8

Animating SVG — three ways

There are three ways to make SVG move. CSS is the one you'll use most:

ApproachHowBest for
CSStransition & @keyframes on shapesMost things — hovers, loops, draw-ins.
SMIL<animate> / <animateTransform> inside the SVGSelf-contained, declarative motion (no CSS/JS).
JavaScriptGSAP, anime.js, or the Web Animations APIComplex sequencing, scroll-driven, interactivity.

CSS keyframes (a looping pulse)

SMIL: <animateTransform> (rotates itself, no CSS)

<animateTransform type="rotate" … repeatCount="indefinite">
<rect x="42" y="42" width="36" height="36">
  <animateTransform attributeName="transform" type="rotate"
    from="0 60 60" to="360 60 60" dur="3s" repeatCount="indefinite"/>
</rect>
CSS animation of SVG is identical to animating HTML (see the Animation lesson) — the only twist is the transform-box gotcha from Step 7. For anything elaborate, drive it with GSAP.
Step 9

The signature effect: self-drawing lines

The most beloved SVG trick. A dashed stroke can be offset to hide itself, then the offset animated to 0 so the line appears to draw itself. Hit replay:

stroke-dasharray & stroke-dashoffset animated to 0
/* pathLength="1" normalizes the length, so this works on any path */
path { stroke-dasharray: 1; stroke-dashoffset: 1; }   fully hidden
path.go { animation: draw 2s ease forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }
The pathLength="1" trick is the pro move: it makes the path report its length as exactly 1, so dasharray: 1 always covers it perfectly — no need to measure the real length with JavaScript.
Step 10

SVG checklist

Where next

Keep going