Icons are everywhere in a modern interface, and the best way to render them is almost always SVG, or Scalable Vector Graphics. Because an SVG is defined as vectors in XML rather than as a grid of pixels, it stays perfectly crisp at any size, on any screen, from a tiny button to a retina display. That alone makes it the natural choice, but SVG icons also outclass the old icon-font approach on several fronts: they style and animate directly with CSS, they support accessibility properly through built-in title and description elements, and they tend to be small and need no font file to download. This article covers the three ways to put SVG icons on a page, the trade-offs between them, and the practices that keep them accessible and tidy.
Inline SVG: the most control
The most powerful method is to drop the SVG markup straight into your HTML. Because the SVG’s elements are now part of the page, you can target them with CSS like any other element, which means you can colour, hover, and animate the icon freely.
<svg class="icon icon-home" viewBox="0 0 64 64" aria-hidden="true"> <title>Home</title> <path d="M32 12l22 22h-6v18h-12v-12h-8v12h-12v-18h-6z"/></svg>
.icon { width: 2rem; height: 2rem; fill: #3498db; transition: fill 0.3s ease;}.icon:hover { fill: #2980b9;}
The key property here is fill, which sets the icon’s colour, and because the SVG path is a real element you can transition it, change it on hover, or animate it just as you would any CSS property. This is what makes inline SVG the right choice for interactive icons that need to respond to the user. The cost is markup: the full SVG sits in your HTML, which can become repetitive if you use the same icon many times, a problem we return to below.
SVG as a background image: separating icon from markup
The second method references the SVG file as a CSS background, which keeps the icon out of your HTML structure entirely.
.icon-settings { width: 32px; height: 32px; background: url('icons/settings.svg') no-repeat center/contain; display: inline-block;}
This is clean when the icon is purely decorative and you would rather not clutter the markup, and you still control size, position, and repetition through normal background properties. The trade-off is reach: because the SVG is now an external image rather than inline elements, you cannot style its internal paths, so changing its colour on hover the way inline SVG allows is not directly possible, though you can still apply CSS filters for some effects. Use this when the icon is a fixed background flourish rather than something you need to recolour or animate from the outside.
The img or object tag: the simplest route
The third method loads the SVG like any other image, with an img tag.
<img src="icons/search.svg" alt="Search" class="icon-search">
.icon-search { width: 24px; height: 24px;}
This is the simplest approach and the one to reach for when you just need to display an icon at a set size with no styling. You can size and position it, but you have no access to the SVG’s internals for colouring or animation. The object tag is a related option that loads the SVG with a little more capability, but for plain display, an img with sensible dimensions and alt text is usually all you need.
Choosing between the three
The decision comes down to how much control you need against how clean you want your markup. Reach for inline SVG when the icon must be coloured, hovered, or animated, since it gives you full CSS access to the paths. Use a background image when the icon is decorative and you want it out of the HTML, accepting limited styling in return. And use an imgtag for the simplest case, a static icon shown at a fixed size. Most projects end up using more than one method, matching each to the job.
Habits that keep icons accessible and tidy
A few practices matter regardless of method. Accessibility comes first. For inline SVGs that convey meaning, include a title element to give the icon an accessible name, and a desc for a longer description when useful. For a purely decorative inline icon, mark it aria-hidden="true" so screen readers skip it, as in the home example above. When you use an img, give it meaningful alt text if it carries meaning, or empty alt if it is decorative. Getting this right means assistive technology describes the icons that matter and ignores the ones that do not.
Beyond accessibility, optimise your files, since SVGs exported from design tools often carry a lot of redundant data, and a tool like SVGO strips that out to shrink the file and speed up loading. Keep styling consistent by defining shared icon classes for size, colour, and hover behaviour, rather than restyling each icon individually, which is what gives a set of icons a uniform look. And avoid drowning your HTML in repeated inline SVGs: when you use the same icons in many places, an SVG sprite, a single file holding all your icons that you reference by id, removes the duplication while keeping the styling control that inline SVG gives you.
Conclusion
SVG is the right foundation for icons because it scales without ever blurring, styles and animates with CSS, and supports accessibility properly. Inline SVG gives you the most control and is the choice for interactive, colour-changing icons, a background image keeps decorative icons out of your markup at the cost of styling, and an img tag is the simplest way to show a static icon. Layer on the good habits, accessible names and descriptions, optimised files, shared icon classes, and sprites when an icon repeats, and you get crisp, flexible, accessible icons across your whole site without a single pixel-based image.
See you soon.
[…] CSS Icons and SVG […]