Skip to main content

πŸ–ŠοΈ SVG Fundamentals and Implementation

SVG is the web's language for graphics that never blur β€” icons, logos, charts, and diagrams described with math instead of pixels. In this lesson you'll learn how SVG thinks, draw every core shape, decode the powerful <path> syntax, and finish with an accessible, interactive bar chart built entirely from vector elements.

🎯 Learning Objectives

By the end of this lesson, you will be able to:

  • Explain how vector graphics differ from raster images and when to choose each
  • Write the basic SVG shapes (rect, circle, ellipse, line, polyline, polygon) with correct attributes
  • Read and write path commands (M, L, C, Q, A, Z) and understand absolute vs. relative coordinates
  • Style SVG with attributes and CSS, and reuse shapes with <g>, <defs>, <symbol>, and <use>
  • Build an accessible interactive chart with <title>, <desc>, and ARIA

Estimated Time: 35–45 minutes  β€’  Difficulty: Beginner–Intermediate

Hands-on: Hand-code a simple logo, then add hover interactivity to an SVG bar chart.

In This Lesson

What Is SVG?

Scalable Vector Graphics (SVG) is an XML-based format for describing two-dimensional graphics. Instead of storing a grid of colored pixels the way a JPEG or PNG does, SVG stores instructions: "draw a circle here with radius 40," "connect these points with a line." The browser follows those instructions to redraw the image fresh at whatever size it needs.

πŸ’‘ A useful analogy: A raster image is a mosaic made of tiny tiles β€” zoom in and you see the individual squares. A vector image is a recipe for drawing shapes, so the browser re-bakes it crisply at any size. One is a photograph of a drawing; the other is the drawing's blueprint.
flowchart LR A[SVG file] -->|written as| B[XML markup] B -->|rendered as| C[Vector graphics] C -->|stays crisp at| D[Any scale] C -->|styled by| E[CSS] C -->|controlled by| F[JavaScript]

Because SVG is just text markup that lives in the DOM, it inherits superpowers that raster images can't have:

  • Scalability β€” razor-sharp from a 16px favicon to a billboard
  • Small files β€” a logo can be a few hundred bytes
  • Styleable β€” CSS targets individual shapes, including :hover
  • Scriptable β€” JavaScript can create, move, and animate elements
  • Accessible β€” text stays real text; shapes can carry descriptions

Vector vs. Raster

Neither format is "better" β€” they solve different problems. The rule of thumb: vectors for anything geometric (icons, logos, UI, diagrams, charts) and raster for anything photographic (photos, textures, painted artwork).

FeatureSVG (vector)PNG / JPEG (raster)
ScalingPerfect at any sizePixelates when enlarged
Best forIcons, logos, charts, diagramsPhotos, complex textures
File sizeTiny for simple graphicsSmaller for detailed photos
AnimationNative via CSS / JSNeeds GIF frames or video
InteractivityPer-element eventsWhole image only
AccessibilityReal text & descriptionsalt text only
Vector versus raster at high zoom A vector cross stays smooth when scaled up, while a raster square breaks into visible pixel blocks. SVG (vector) Always sharp PNG (raster) Becomes blocky
Figure 1 β€” Zoomed in, the vector cross keeps clean edges while the raster square dissolves into pixel blocks. That difference is why every icon in a modern UI is SVG.

πŸ’‘ Use both together

Most sites combine the two: SVG for the interface (icons, logos, charts) and raster for content photos. You don't pick a side β€” you pick the right tool per asset.

Structure & Coordinate System

An SVG is a root <svg> element containing shape elements. Here's the smallest useful example β€” a single circle:

<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="40" fill="crimson" stroke="black" stroke-width="2" />
</svg>
  • width/height β€” the on-screen size (can be overridden by CSS)
  • viewBox="min-x min-y width height" β€” the internal coordinate space the shapes are drawn in. This is what makes SVG responsive: set width:100% in CSS and the viewBox scales to fit
  • xmlns β€” the XML namespace (required for standalone .svg files)

πŸ“– Key Terms

viewBox: the coordinate window. 0 0 100 100 means "coordinates run 0–100 in both directions," regardless of the pixel size on screen.

Origin: the point (0, 0) sits at the top-left. X increases to the right, Y increases downward β€” the opposite of the Cartesian graphs from math class.

SVG coordinate system The origin is at the top-left; X increases rightward and Y increases downward. A sample point at 150 by 100 is marked. X β†’ Y ↓ (0, 0) (150, 100)
Figure 2 β€” Unlike a math graph, SVG's Y-axis points down. Point (150, 100) is 150 units right and 100 units down from the top-left origin.

The Basic Shapes

SVG ships with a handful of primitive shapes. Combine them and you can draw almost anything.

ShapeElementKey attributes
Rectangle<rect>x y width height rx ry
Circle<circle>cx cy r
Ellipse<ellipse>cx cy rx ry
Line<line>x1 y1 x2 y2
Polyline<polyline>points
Polygon<polygon>points (auto-closed)
Path<path>d (anything)
<svg viewBox="0 0 300 80" xmlns="http://www.w3.org/2000/svg">
  <rect    x="10" y="15" width="50" height="50" rx="8" fill="#3b82f6" />
  <circle  cx="105" cy="40" r="25" fill="#22c55e" />
  <ellipse cx="175" cy="40" rx="30" ry="18" fill="#f59e0b" />
  <polygon points="240,15 265,65 215,65" fill="#a855f7" />
</svg>
The core SVG shapes A rectangle, circle, ellipse, line, polyline, and polygon rendered side by side with labels. rect circle ellipse line polyline polygon
Figure 3 β€” The primitive shapes. A polyline stays open; a polygon automatically connects its last point back to its first.

The Path Element

The <path> is the most powerful shape β€” every other shape can be expressed as a path. It draws using a mini-language in its d ("data") attribute, a sequence of single-letter commands followed by coordinates.

CommandMeansExample
M / mMove to (pen up)M10,10
L / lLine toL90,90
H / VHorizontal / vertical lineH50 Β· V30
C / cCubic BΓ©zier curveC10,10 20,20 30,30
Q / qQuadratic BΓ©zier curveQ10,10 20,20
A / aElliptical arcA30,30 0 0 1 60,60
Z / zClose pathZ

Uppercase means absolute coordinates; lowercase means relative. Think of uppercase as GPS coordinates ("go to this exact spot") and lowercase as walking directions ("move 10 steps forward from where you are").

Here's a heart drawn with two cubic curves β€” the classic path demo:

<svg width="120" height="120" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <path d="M50,88
           C10,55 10,20 35,20
           C48,20 50,33 50,33
           C50,33 52,20 65,20
           C90,20 90,55 50,88 Z"
        fill="crimson" />
</svg>

⚠️ Don't hand-draw complex paths

Reading path syntax is a valuable skill, but you rarely author intricate shapes by hand. Design in Figma, Illustrator, or Inkscape and export the SVG β€” then optimize it. Hand-editing is for tweaks and understanding, not for drawing a company logo point by point.

Styling & Reuse

Presentation attributes vs. CSS

You can style SVG two ways: with presentation attributes directly on the element, or with CSS. CSS wins for anything shared, interactive, or animated.

<!-- Presentation attributes (inline) -->
<circle cx="50" cy="50" r="40" fill="royalblue" stroke="black" stroke-width="2" />

<!-- Or with CSS -->
<style>
  .dot { fill: royalblue; stroke: black; stroke-width: 2; transition: fill .3s; }
  .dot:hover { fill: tomato; }   /* impossible with a raster image */
</style>
<circle class="dot" cx="50" cy="50" r="40" />

The common styling properties are fill, stroke, stroke-width, fill-opacity, stroke-opacity, stroke-linecap, stroke-linejoin, and stroke-dasharray (for dashed lines).

Group, define, and reuse

Three elements keep complex SVGs manageable β€” and they map neatly onto ideas you already know from components:

  • <g> β€” a group. Apply one transform or style to many shapes at once.
  • <defs> β€” a definitions block: shapes declared but not drawn until referenced.
  • <symbol> + <use> β€” define a reusable icon once, stamp it anywhere (like a component).
<svg viewBox="0 0 200 60" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <symbol id="star" viewBox="0 0 100 100">
      <polygon points="50,5 61,38 96,38 68,59 79,92 50,72 21,92 32,59 4,38 39,38" />
    </symbol>
  </defs>

  <use href="#star" x="10"  y="10" width="40" height="40" fill="gold" />
  <use href="#star" x="80"  y="10" width="40" height="40" fill="silver" />
  <use href="#star" x="150" y="10" width="40" height="40" fill="#cd7f32" />
</svg>

βœ… Why <use> matters

Define the shape once, reuse it dozens of times, and each copy can override the fill or size. It's the same "write once, reuse everywhere" principle behind UI components β€” smaller files and a single source of truth.

Worked Example: Interactive Chart

Let's tie it together. Because inline SVG lives in the DOM, each bar can carry data attributes and respond to events β€” something a chart image could never do. Here's a compact, accessible bar chart with a hover tooltip.

<figure>
  <svg id="sales" width="480" height="280" viewBox="0 0 480 280"
       role="img" aria-labelledby="chartTitle chartDesc">
    <title id="chartTitle">Monthly sales, 2025</title>
    <desc id="chartDesc">Bar chart; sales peak in April at 55,000.</desc>

    <!-- axis -->
    <line x1="40" y1="240" x2="460" y2="240" stroke="#94a3b8" />

    <!-- bars: height and data live on each rect -->
    <rect class="bar" x="60"  y="140" width="40" height="100" data-month="Jan" data-value="25000" />
    <rect class="bar" x="130" y="100" width="40" height="140" data-month="Feb" data-value="35000" />
    <rect class="bar" x="200" y="60"  width="40" height="180" data-month="Mar" data-value="45000" />
    <rect class="bar" x="270" y="20"  width="40" height="220" data-month="Apr" data-value="55000" />
    <rect class="bar" x="340" y="80"  width="40" height="160" data-month="May" data-value="40000" />
  </svg>
  <div id="tip" class="tip" role="status"></div>
</figure>

<style>
  .bar { fill: #3b82f6; transition: fill .2s; cursor: pointer; }
  .bar:hover, .bar:focus { fill: #f59e0b; }
  .tip { position: absolute; padding: 6px 10px; background: #1e293b; color: #fff;
         border-radius: 6px; pointer-events: none; opacity: 0; transition: opacity .2s; }
</style>

<script>
  const tip = document.getElementById('tip');
  for (const bar of document.querySelectorAll('.bar')) {
    bar.addEventListener('mousemove', (e) => {
      const value = Number(bar.dataset.value).toLocaleString();
      tip.textContent = `${bar.dataset.month}: $${value}`;
      tip.style.left = `${e.pageX + 12}px`;
      tip.style.top  = `${e.pageY - 36}px`;
      tip.style.opacity = '1';
    });
    bar.addEventListener('mouseleave', () => { tip.style.opacity = '0'; });
  }
</script>

What this demonstrates

  • Data stored on each element with data-* attributes
  • CSS :hover/:focus transitions for instant visual feedback
  • A modern for…of loop with template literals and toLocaleString()
  • Built-in accessibility via role="img", <title>, and <desc>

Hands-on Exercise

πŸ‹οΈ Build (and animate) a logo

Objective: Practice shapes, grouping, and CSS interactivity by hand-coding a small logo.

Instructions:

  1. Create an SVG with viewBox="0 0 100 100".
  2. Use at least three different shape types (e.g. a circle backdrop, a polygon mark, a path flourish).
  3. Wrap them in a <g> and add a CSS :hover rule that changes a fill or scales the group.
  4. Add a <title> so the logo has an accessible name.
πŸ’‘ Hint

Set transform-box: fill-box; transform-origin: center; on the group so transform: scale(1.1) grows from the middle instead of the top-left corner.

βœ… Sample solution
<svg viewBox="0 0 100 100" width="120" role="img" aria-labelledby="logoTitle">
  <title id="logoTitle">Rocket badge logo</title>
  <g class="logo">
    <circle cx="50" cy="50" r="46" fill="#0f172a" />
    <polygon points="50,20 62,55 38,55" fill="#f59e0b" />
    <path d="M42,55 Q50,72 58,55 Z" fill="#ef4444" />
  </g>
</svg>
<style>
  .logo { transform-box: fill-box; transform-origin: center; transition: transform .3s; }
  svg:hover .logo { transform: scale(1.1); }
</style>

🎯 Quick Quiz

Question 1: Which attribute defines the internal coordinate space that lets an SVG scale responsively?

Question 2: In a path's d attribute, what does a lowercase command letter such as l indicate?

Question 3: You need a photo of a product on your page. Which format is the right choice?

Best Practices

βœ… Do

  • Add a viewBox and control size with CSS for responsive graphics
  • Give meaningful SVGs role="img", a <title>, and a <desc>
  • Optimize exported files with SVGOMG to strip editor cruft
  • Reuse repeated shapes with <symbol> and <use>
  • Prefer CSS for hover states and animation

⚠️ Don't

  • Ship raw editor exports full of metadata, IDs, and redundant groups
  • Hand-author complex paths when a design tool can generate them
  • Forget alt text β€” an <img src="logo.svg"> still needs an alt attribute
  • Use createElement for SVG in JS β€” it must be createElementNS with the SVG namespace

Summary & Quiz

πŸŽ‰ Key Takeaways

  • SVG describes graphics with math, so they stay crisp at any size.
  • Use vectors for geometry (icons, logos, charts) and raster for photos.
  • The viewBox plus CSS sizing is what makes SVG responsive.
  • The <path> element can draw anything; uppercase = absolute, lowercase = relative.
  • Inline SVG lives in the DOM, so shapes can be styled, scripted, and made accessible.

πŸ“š Further Reading

πŸš€ What's Next?

SVG is one of the two ways to draw on the web. Next we meet the other: the Canvas API, a pixel-based drawing surface that trades SVG's DOM friendliness for raw rendering speed β€” perfect for games and heavy animation.

πŸŽ‰ Nice work!

You can now read, write, style, and script vector graphics. Let's switch to painting pixels.