Command Palette

Search for a command to run...

Hectal
PHASE 5Intermediate ~22 min· topic 6 of 7

Topic 5.6

SVG in HTML

In one line

SVG describes pictures as shapes instead of pixels, so they stay sharp at any size; written inline in HTML, every shape is an element you can colour with CSS, which makes SVG ideal for icons, logos and simple graphics.

Think of it like this

A recipe versus a photo of a cake. A photo (a raster image like JPEG or PNG) is a fixed grid of coloured dots; blow it up and it gets blocky. A recipe (SVG) says "a round cake, 20 cm wide, chocolate icing"; you can bake it at any size and it comes out perfect. SVG stores instructions for drawing, not the dots.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

SVG
Scalable Vector Graphics: a tag-based language for drawings made of shapes.
Vector
An image stored as shapes and maths, not pixels, so it stays sharp at any size.
Raster
An image stored as a grid of pixels, like JPEG or PNG. It gets blurry when enlarged.
viewBox
The SVG's own coordinate grid: min-x min-y width height. It's what lets the drawing scale.
path
An SVG shape drawn with commands like M (move), L (line) and Z (close).
fill
The colour inside a shape.
stroke
The colour of a shape's outline.
currentColor
A colour value meaning "the current text colour", great for icons.
Inline SVG
An <svg> written directly inside the HTML, so its shapes are part of the page.

Step by step

01Draw on a grid

Start with a 100 × 100 viewBox. Coordinates count from the top-left corner. A circle centred at 50,50 with radius 40 sits in the middle with 10 units of space around it.

index.htmlwhole filehtml
<svg viewBox="0 0 100 100" width="100" height="100">
  <circle cx="50" cy="50" r="40" fill="gold" />
</svg>
Draw on a griddiagram
Rendering diagram…

02Add more shapes

Shapes are drawn in order, so later shapes sit on top. Here: a sky rectangle, a sun circle, and a mountain drawn with a path (move to bottom-left, line to the peak, line to bottom-right, close).

index.htmlwhole filehtml
<svg viewBox="0 0 100 60" width="300" height="180">
  <rect x="0" y="0" width="100" height="60" fill="skyblue" />
  <circle cx="80" cy="15" r="8" fill="gold" />
  <path d="M 0 60 L 40 20 L 75 60 Z" fill="seagreen" />
</svg>

03Outline with stroke

fill="none" makes a shape hollow; stroke and stroke-width draw the outline. Many icon sets are outlines like this.

index.htmlwhole filehtml
<svg viewBox="0 0 24 24" width="48" height="48">
  <path d="M3 12 L9 18 L21 6" fill="none" stroke="green" stroke-width="2.5"
        stroke-linecap="round" stroke-linejoin="round" />
</svg>

04Turn it into an icon

Use currentColor so the icon follows the text colour. A decorative icon next to a text label gets aria-hidden="true" so screen readers skip it; the button's text gives the name.

index.htmlwhole filehtml
<button class="save">
  <svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true">
    <path d="M3 12 L9 18 L21 6" fill="none" stroke="currentColor" stroke-width="2.5" />
  </svg>
  Save
</button>

05An icon with no text needs a name

If the icon is the only content, give the control an accessible name. Put aria-label on the button, or use role="img" with a <title> when the SVG itself carries meaning (like a chart).

index.htmlwhole filehtml
<button aria-label="Close">
  <svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true">
    <path d="M6 6 L18 18 M18 6 L6 18" stroke="currentColor" stroke-width="2" />
  </svg>
</button>

<svg role="img" aria-labelledby="t1" viewBox="0 0 100 60">
  <title id="t1">Sales rose from 20 to 50 this year</title>
  ...
</svg>

06Reuse icons with a sprite

Define each icon once as a <symbol> in a hidden SVG, then show it anywhere with <use href="#id">. Each use can be a different size and colour.

index.htmlwhole filehtml
<svg style="display:none">
  <symbol id="icon-star" viewBox="0 0 24 24">
    <path d="M12 2 L15 9 L22 9 L16.5 13.5 L18.5 21 L12 16.8 L5.5 21 L7.5 13.5 L2 9 L9 9 Z" />
  </symbol>
</svg>

<svg width="24" height="24" fill="currentColor" aria-hidden="true"><use href="#icon-star" /></svg>

Try it yourself

  1. 1

    Move the sun

    In the first example, predict where the sun goes if you change cx="80" to cx="20" in the big picture. Then make it bigger with r="12".

  2. 2

    Crop with viewBox

    Change the big picture's viewBox to 0 0 50 30. Predict: you're now showing only the top-left quarter of the grid, scaled up to fill the same box. Run it to check.

  3. 3

    Recolour every icon

    In the icons example, change .love { color: … } to color: rebeccapurple;. Both heart icons change, though you never touched the SVG.

Code & diagrams

Shapes, viewBox and scaling New tab

Both pictures use identical shapes. Only `width` and `height` differ, and the bigger one is just as sharp: zoom in with Ctrl and + to check.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

viewBox: 0 0 100 60
Shown at: 300px wide
Scale factor: 3
Sun radius in drawing units: 8
Icons that follow the text colour New tab

Each icon is defined once and reused with `<use>`. Hover over a heart: the icon changes colour with the text because it uses `currentColor`. `1.25em` of a 16px font is 20px.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

Button text colour: rgb(0, 128, 0)
Icon size follows the font: 20px
Last button's accessible name comes from: Like
img versus inline: who can CSS reach? New tab

The CSS turns the inline circle tomato (CSS beats the `fill` attribute). The image's circle lives in a separate document that your CSS and JavaScript can't see.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

Circles in this page's DOM: 1
Inline circle fill: rgb(255, 99, 71)

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Forget the viewBox

Remove viewBox="0 0 100 60" from the big picture in the first example.

terminal
$ the page shows
── what you'll see ──
The drawing stays small in the top-left corner of the 300 × 180 box; the rest is empty.

Break #2

Expect CSS to recolour an SVG image

Show an icon with <img src="icon.svg"> and write img path { fill: red; }.

terminal
$ the page shows
── what you'll see ──
The icon keeps its original colour.

Myth vs fact

Myth

SVG is always smaller than PNG.

Fact

For simple icons and logos, yes. For detailed artwork with thousands of paths, an SVG can be bigger and slower to draw than a PNG or WebP.

Myth

SVG files are just images, so they're safe to accept from users.

Fact

SVG can contain scripts and links. Opened directly from your domain, a malicious SVG could run script there. Sanitise uploaded SVGs, serve user uploads from a separate domain, and display them with <img>, where scripts don't run.

Myth

An inline SVG is invisible to screen readers anyway.

Fact

Browsers may expose its contents, including <text>. Mark decorative SVGs aria-hidden="true" and give meaningful ones role="img" plus a name.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    Inline SVG elements live in the SVG namespace (http://www.w3.org/2000/svg). The HTML parser switches namespace automatically inside <svg>, but JavaScript must use document.createElementNS("http://www.w3.org/2000/svg", "circle"); createElement("circle") makes an unknown HTML element that draws nothing.

  • ▸

    preserveAspectRatio controls how the viewBox fits a box with a different shape: the default xMidYMid meet centres and fits entirely (like object-fit: contain); slice fills and crops (like cover); none stretches.

  • ▸

    Presentation attributes like fill="gold" have the lowest priority: any CSS rule (even a plain type selector) overrides them. That's why circle { fill: tomato } wins in the example.

  • ▸

    Optimise SVGs from design tools with SVGO (or the SVGOMG web app): it removes editor metadata and shortens paths, often halving the file.

Remember this

  1. 1

    SVG (Scalable Vector Graphics) is a markup language for 2D drawings, written in tags like HTML. A vector image is made of shapes described by maths (lines, curves, circles), so the browser redraws it sharply at any size and on any screen density. SVG is best for icons, logos, charts, diagrams and illustrations with flat colours; photos stay JPEG/WebP/AVIF.

  2. 2

    You can write an <svg> element inline, right inside your HTML. Inside it go shapes: <rect x="10" y="10" width="80" height="40"> (a rectangle from its top-left corner), <circle cx="50" cy="50" r="40"> (centre x, centre y, radius), <line>, <polygon>, <text> and the most powerful one, <path>. Coordinates start at the top-left corner and y grows downwards, unlike maths class.

  3. 3

    **viewBox** is the key idea. viewBox="0 0 100 100" says "my drawing lives on a 100 × 100 grid starting at 0,0". Separately, width and height (or CSS) say how big the SVG appears on the page. The browser scales the grid to fit: draw once on a 24 × 24 grid, show it at 16px or 160px, and it stays sharp. Without a viewBox, the drawing doesn't scale; it gets cropped or leaves empty space instead.

  4. 4

    **<path d="…">** draws any shape with short commands: M x y moves the pen without drawing, L x y draws a line, H and V draw horizontal and vertical lines, C and Q draw curves, A draws an arc and Z closes the shape back to the start. Capital letters use absolute coordinates; lowercase use relative ones (from the last point). Icon libraries are mostly paths.

  5. 5

    **fill colours the inside of a shape (default black) and stroke** colours its outline, with stroke-width for thickness. Set them as attributes or with CSS. The special value **currentColor** means "use the text colour", so an icon inside a red link turns red, and changes on hover, with no extra CSS.

  6. 6

    **<img src="logo.svg"> versus inline <svg>.** As an <img>, the SVG is a separate file that can be cached; it's treated like any picture: your CSS can't reach its shapes, scripts inside it don't run, and alt describes it. Inline, the shapes become part of your page's DOM: you can style them, animate them and change them with JavaScript, but the markup is repeated on every page and isn't cached separately. Rule of thumb: inline for small icons you colour with CSS; <img> for logos and illustrations.

Explain it without notes

01

What is the difference between vector and raster images, and when is SVG the right choice?

02

What does viewBox do, and how does it relate to width and height?

03

Compare <img src="icon.svg"> with inline <svg>.

04

How do you make an SVG icon accessible, both when it's decorative and when it's the only content of a button?

Practice

01

Draw a 100 × 100 SVG of a traffic light: a dark rounded rectangle with red, amber and green circles stacked vertically.

02

Make a "Delete" button with a decorative cross icon that turns red on hover along with the text.

Trade-offs

  • ↔

    Inline SVG gives full styling control but bloats HTML and isn't cached; a sprite file referenced with <use href="icons.svg#star"> is cached but needs a same-origin URL.

  • ↔

    Icon fonts were once popular for icons, but they fail when fonts don't load and are poor for accessibility; SVG icons are the modern choice.

Done when you can

  • I can draw rectangles, circles and paths inside an <svg>.

  • I can explain viewBox and make a drawing scale.

  • I can use fill, stroke and currentColor.

  • I can choose between <img> and inline SVG.

  • I can make SVG icons accessible.