SVG Fundamentals for Icons
Updated on
Scalable Vector Graphics, or SVG, is the default format for most web icons for good reason. It scales cleanly, stays light when the artwork is simple, and gives you proper control over styling. This page covers the parts that matter in practice: structure, viewBox, path commands, shapes, styling, sprites, accessibility, and browser support.
SVG as a vector format
SVG is an XML-based markup language for two-dimensional vector graphics. Unlike PNG or JPEG, it is resolution-independent, so the same icon can be used at 16 pixels, 24 pixels, or far larger without soft edges or awkward resampling. That is exactly why it suits interface icons, which need to survive across screen densities and layout changes.
For the complete specification and documentation, refer to the W3C SVG specification.
A minimal icon file
A basic SVG document has a clear structure. Here is a stripped-down icon example:
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24">
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
</svg>These are the pieces that actually matter:
- xmlns - The SVG namespace declaration, required for standalone files
- viewBox - The coordinate system, set as min-x, min-y, width, height
- width/height - The default rendering size
- path - The vector shape drawn with path commands
Why viewBox does the heavy lifting
The viewBox is what keeps an icon flexible. It creates a coordinate system that is separate from the display size, so the same graphic can be rendered at different dimensions without distortion. A viewBox of "0 0 24 24" means the coordinate system starts at (0, 0), the visible area is 24 units wide and 24 units tall, and the icon keeps its aspect ratio as it scales.
Common viewBox sizes for icons are 16x16, 20x20, 24x24, and 32x32. The right choice usually comes down to the design grid you are working on and where the icon will be used. There is no prize for picking a size that looks neat in a code sample and awkward everywhere else.
Drawing with path commands
The path element's d attribute contains the drawing instructions. The main commands are M for moveto, L for lineto, H for horizontal lineto, V for vertical lineto, C for cubic Bézier curves, S for smooth cubic Bézier curves, Q for quadratic Bézier curves, A for arcs, and Z for closing the current path.
Uppercase commands use absolute coordinates. Lowercase commands use relative coordinates from the current point. That distinction matters more than it looks at first glance, especially when paths get longer and you are trying to edit them without turning the whole file into a small crime scene.
Simple shapes are often enough
SVG also includes primitive shapes that are easier to read than a path when the artwork is simple:
- rect - Rectangles and squares
- circle - Circles defined by centre and radius
- ellipse - Ellipses with horizontal and vertical radii
- line - Straight lines between two points
- polyline - A connected series of straight lines
- polygon - Closed shapes with straight sides
A path can represent any of these, but there is no need to force everything through one tool. Using semantic shapes keeps the markup easier to scan and usually makes styling simpler too.
Styling icons with CSS
SVG elements can be styled inline, in a style block, or from an external stylesheet. For icon work, the properties that tend to matter are fill, stroke, stroke-width, stroke-linecap, stroke-linejoin, and opacity. The rest is usually noise unless the artwork is doing something more complex than a simple interface icon.
- fill - Interior colour of shapes
- stroke - Outline colour
- stroke-width - Thickness of strokes
- stroke-linecap - Shape of stroke endpoints: butt, round, or square
- stroke-linejoin - Shape of stroke corners: miter, round, or bevel
- opacity - Transparency level
Using currentColor
Setting fill="currentColor" makes the icon inherit the text colour from its parent element. That is useful when the icon needs to sit beside text without looking pasted on.
<svg fill="currentColor" viewBox="0 0 24 24"> <path d="..."/> </svg>
Inline SVG, image files, and background use
SVGs can be included in HTML in a few different ways. Inline SVG sits directly in the markup and allows CSS styling plus JavaScript interaction. An img tag such as <img src="icon.svg"> is simpler, but it cannot be styled with CSS in the same way. CSS background images work well for decorative icons. object and embed exist too, though they are less common and only occasionally worth the trouble.
For icons that need to match text colour or respond to hover and focus states, inline SVG is usually the cleaner option.
SVG sprites in practice
SVG sprites combine multiple icons into one file, which cuts down on HTTP requests. The icons are defined as symbols and then referenced with the use element:
<!-- Define sprite (hidden) -->
<svg style="display: none">
<symbol id="icon-home" viewBox="0 0 24 24">
<path d="..."/>
</symbol>
<symbol id="icon-settings" viewBox="0 0 24 24">
<path d="..."/>
</symbol>
</svg>
<!-- Use icons -->
<svg><use href="#icon-home"/></svg>
<svg><use href="#icon-settings"/></svg>Making icons accessible
SVG icons should be treated like any other interface content. Add role="img" when the icon carries meaning, use aria-label or aria-labelledby to provide a description, and mark purely decorative icons with aria-hidden="true" when they sit alongside visible text labels. A <title> element is also useful when you want tooltip text.
What browser support actually looks like
SVG support is strong across modern browsers. Basic features work in Internet Explorer 9+ and in current versions of Chrome, Firefox, Safari, and Edge. Some advanced features, including CSS transforms and filters, can behave slightly differently from browser to browser, so it pays to test anything more ambitious than a static icon.