Skip to main content
Technical

SVG Fundamentals for Icons

Updated on

SVG (Scalable Vector Graphics) is the standard format for icons on the modern web. The useful parts are not complicated, but they do need to be understood properly: coordinate systems, paths, presentation attributes, and the accessibility hooks that stop an icon from becoming noise.

Why SVG is the default for icon work

Unlike raster formats such as PNG and WebP, SVGs describe shapes mathematically. They stay crisp at any display density, including high-DPI retina screens, without needing separate image variants for every size. Simple icons are often only a few hundred bytes, which is one reason they are still the sensible choice for interface work.

For an authoritative overview of SVG capabilities and the specification itself, see the W3C SVG overview.

Reading the SVG coordinate system

Every SVG has its own internal coordinate system. The origin, 0, 0, sits in the top-left corner. X values move to the right. Y values move down. That sounds obvious until you are reading path data by hand and a shape lands somewhere you did not expect.

Using the viewBox attribute properly

The viewBox attribute is the key setting on the root <svg>element for icons. It defines the portion of the coordinate system that gets displayed:

  • viewBox="0 0 24 24" - a 24x24 unit canvas, origin at top-left
  • viewBox="0 0 16 16" - common for small UI icons
  • viewBox="-12 -12 24 24" - centred origin, useful for symmetric shapes

Set viewBox, remove fixed width and height, and the SVG will scale proportionally wherever it is placed. Size it through CSS. That is the part people often skip, then wonder why the icon keeps ignoring their layout rules.

Path data and the commands inside it

The <path> element does most of the work in SVG icons. Its d attribute contains drawing commands:

  • M / m - Move to, absolute or relative
  • L / l - Line to
  • H / h - Horizontal line
  • V / v - Vertical line
  • C / c - Cubic Bézier curve
  • A / a - Elliptical arc
  • Z / z - Close path

Uppercase commands use absolute coordinates. Lowercase commands stay relative to the current position. Most design tools generate path data for you, but the commands still matter when you are editing an icon by hand or checking the output of an optimiser. If you are evaluating AI-powered generators for producing icon artwork, checking a best image ai roundup can help you choose tools whose SVG export is clean and needs minimal manual cleanup.

How fill and stroke paint a shape

Two presentation attributes control how SVG shapes are painted. fill colours the interior of closed shapes, and stroke colours the outline. Set fill to none when you want an outline-only icon. Use stroke-width when the line thickness needs to be explicit.

Why currentColor is usually the cleanest choice

Setting fill="currentColor" or stroke="currentColor" lets the icon inherit the CSS color value from its parent element. For UI icons, that is usually the right call. It adapts to dark mode, follows hover and focus states defined in CSS, works across colour-themed component systems, and does not need JavaScript to keep up.

A basic SVG icon structure

A well-formed SVG icon usually follows a simple pattern:

<svg xmlns="http://www.w3.org/2000/svg"
     viewBox="0 0 24 24"
     fill="currentColor"
     aria-hidden="true">
  <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
</svg>

Four details matter here. The xmlns namespace is required for standalone SVG files. The viewBox sets the 24x24 canvas. fill="currentColor"keeps colour control in CSS. aria-hidden="true" keeps decorative icons out of the screen reader output.

Accessibility rules that usually get missed

Decorative icons should include aria-hidden="true" so assistive technology skips them. If the icon carries meaning - a standalone button with no visible label is the common example - give it a text alternative instead.

  • Decorative icon, paired with visible label: aria-hidden="true"
  • Meaningful standalone icon: add role="img" and aria-label="Description", or include a <title> child element

Other SVG elements you will actually see

Not every icon is built from <path>. A few other elements turn up often:

  • <circle> - Defined by cx, cy, r
  • <rect> - Rectangles with optional rx/ry for rounded corners
  • <line> - A single straight segment
  • <polyline> / <polygon> - Multi-segment lines and closed polygons
  • <g> - A group element for organising related shapes and applying shared attributes
  • <defs> / <use> - Define a shape once, reuse it multiple times

Inline SVG or an external file?

Icons can be delivered in two ways. Inline SVG embeds the markup directly in HTML. That gives full CSS and JavaScript control, including currentColor, so it is the better fit for UI icons that need to match a design system. External files, whether served through <img src> or a CSS background, are simpler to drop in but much harder to style. They do not respond to currentColor or CSS variables unless you serve them as a data URI.

For icon libraries and component systems, inline SVG is still the standard approach. It gives the most flexibility without adding much overhead.

Frequently Asked Questions

What is a viewBox in SVG?
The viewBox attribute sets the coordinate system and aspect ratio for the SVG canvas. It uses four values: min-x, min-y, width, and height. Get this right and the SVG can scale without distortion.
Should I set width and height on SVG icon elements?
For inline SVGs used as icons, fixed width and height attributes are usually better left out. Pair a viewBox with CSS sizing instead, so the display size stays under your control rather than fighting the stylesheet.
What is the difference between fill and stroke in SVG?
Fill colours the inside of a shape. Stroke colours the outline. Solid icons often use fill, while line icons rely on stroke. Both can take colour values, gradients, or "currentColor" so they inherit from CSS.
When should I use currentColor?
Use currentColor when the icon should pick up the text colour from its parent element. It is the cleanest way to handle dark mode, hover states, and themed components without extra CSS rules.