SVG Basics
<div> or <button>.Inline SVG in HTML
inline-svg.html
<svg width="200" height="100" viewBox="0 0 200 100"> <rect x="10" y="10" width="80" height="60" fill="#3b82f6" /> <circle cx="150" cy="40" r="30" fill="#ef4444" /> </svg>
circle with document.querySelector, or style rect with a CSS rule, exactly like any other element.Basic Shapes
Element | Draws |
|---|---|
<rect> | A rectangle — x, y, width, height (and optional rx for rounded corners) |
<circle> | A circle — cx, cy (center), r (radius) |
<ellipse> | An ellipse — cx, cy, rx, ry |
<line> | A straight line — x1, y1, x2, y2 |
<polygon> | A closed shape from a list of points |
<path> | Any shape, via a compact drawing-command syntax (d attribute) |
basic-shapes.html
<svg width="220" height="100" viewBox="0 0 220 100"> <rect x="0" y="10" width="60" height="60" rx="8" fill="#22c55e" /> <circle cx="110" cy="40" r="30" fill="#3b82f6" /> <line x1="150" y1="10" x2="210" y2="70" stroke="#111827" stroke-width="4" /> </svg>
<path> — Drawing Anything
<path> uses a compact command language in its d attribute: M moves the pen, L draws a line, C draws a curve, and Z closes the shape. Design tools like Figma or Illustrator export shapes as <path> data automatically—you rarely write complex paths by hand.path-example.html
<svg width="100" height="100" viewBox="0 0 100 100"> <!-- Move to (10,80), line to (50,10), line to (90,80), close --> <path d="M10 80 L50 10 L90 80 Z" fill="#f59e0b" /> </svg>
viewBox — SVG's Coordinate System
viewBox="min-x min-y width height" defines the internal coordinate system your shapes are drawn in, independent of the element's rendered size (set by the width/height attributes or CSS). This is what makes SVG truly scalable: the browser stretches the internal coordinate grid to fit whatever box you render it in, with no pixelation.viewbox.html
<!-- Internal coordinates go from (0,0) to (100,100),
but it renders at 400x400 CSS pixels, crisp at any size -->
<svg viewBox="0 0 100 100" style="width: 400px; height: 400px;">
<circle cx="50" cy="50" r="40" fill="#8b5cf6" />
</svg>Styling SVG With CSS
fill and stroke can also be set (and overridden) from an external or embedded stylesheet, including with hover states.svg-css.html
<style>
.icon-star {
fill: #9ca3af;
transition: fill 0.15s ease;
}
.icon-star:hover {
fill: #f59e0b;
}
</style>
<svg width="40" height="40" viewBox="0 0 24 24" class="icon-star">
<path d="M12 2l3 7h7l-5.5 4.5L18 21l-6-4-6 4 1.5-7.5L2 9h7z" />
</svg>Accessibility: title, desc, and aria-hidden
<title> and optionally <desc> as its first children. A purely decorative SVG (an icon next to text that already says the same thing) should be hidden from assistive technology instead.svg-accessible.html
<!-- Meaningful SVG: describe it -->
<svg viewBox="0 0 100 100" role="img" aria-labelledby="chart-title">
<title id="chart-title">Quarterly revenue, trending upward</title>
<path d="M10 80 L40 50 L70 60 L90 20" stroke="#3b82f6" fill="none" stroke-width="3" />
</svg>
<!-- Decorative SVG next to a text label: hide it -->
<button>
<svg aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 24 24">
<path d="M5 12h14M12 5l7 7-7 7" stroke="currentColor" fill="none" stroke-width="2" />
</svg>
Next
</button>aria-hidden="true". A standalone chart with no adjacent text summary does lose meaning, so it needs a real <title>.onclick/event listeners, animate attributes with CSS transitions, or update them with JavaScript—all without a canvas redraw.Referencing an External SVG File
<object> when you need it to keep its own scripting context (see the embed lesson for details on that trade-off).external-svg.html
<!-- As a plain image: simplest, but no CSS styling or scripting from the host page -->
<img src="/icons/logo.svg" alt="Company logo" width="120" height="120" />
<!-- As a CSS background: same limitation, purely decorative use -->
<style>
.hero {
background-image: url('/images/pattern.svg');
}
</style>Method | Can style with page CSS? | Can script per shape? |
|---|---|---|
Inline <svg> | Yes | Yes |
<img src="file.svg"> | No (only via the SVG’s own internal CSS) | No |
CSS background-image | No | No |
<object data="file.svg"> | No, from the host page | Yes, inside the SVG's own scripts |
Grouping Shapes With <g>
<g> groups multiple shapes so they can be transformed, styled, or labeled together—handy for composite icons or diagram components.svg-group.html
<svg viewBox="0 0 100 100">
<g transform="translate(20, 20)" fill="#3b82f6">
<rect width="20" height="20" />
<circle cx="40" cy="10" r="10" />
</g>
</svg>Inline SVG becomes part of the page DOM: inspectable, CSS-stylable, and scriptable per shape.
rect, circle, ellipse, line, and polygon cover common shapes; path draws anything else via its d attribute.
viewBox defines the internal coordinate system, decoupled from the rendered width/height — this is what makes SVG scale crisply.
Style SVG presentation attributes with ordinary CSS, including :hover and other pseudo-classes.
Give meaningful SVGs a <title> (and role="img"); hide purely decorative SVGs with aria-hidden="true".