How to use SVG icons in HTML, CSS, React and Vue
Updated · 7 min read
SVG icons are small vector files, so they stay sharp at every size, weigh a few hundred bytes and can be recolored with CSS. There are four common ways to put one on a page. Which one to use depends on whether you need to style the icon, how many icons the page has and which framework you use.
1. Link the SVG with an <img> tag
The simplest method: treat the icon like any other image. Every icon on Iconyz has a public SVG URL, shown in the icon panel.
<img src="https://iconyz.com/api/public/svg/lucide/house.svg"
width="24" height="24" alt="Home">The browser caches the file, and the icon never blocks your HTML from rendering. The drawback is that CSS can't reach inside an image, so color and :hover styles don't affect it. For monotone icons you can set the color in the URL instead: add ?color=%23e11d48 (a URL-encoded #e11d48). See the SVG API guide for details.
For production apps, consider downloading the SVG and serving it from your own site, so your pages don't depend on a third-party URL.
2. Paste the SVG inline
Open an icon, choose SVG and copy the code straight into your HTML:
<button class="btn">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"
aria-hidden="true">
<path fill="none" stroke="currentColor" stroke-width="2" d="…"/>
</svg>
Home
</button>Inline SVG is part of the page, so CSS controls it completely: color, size, hover states, transitions and even individual paths. Monotone icon sets use currentColor, so the icon automatically takes the text color of its parent. This is the most flexible option and needs no extra HTTP request.
The cost is HTML size. Each inline icon adds its path data to every page that uses it, which matters if you repeat the same icon hundreds of times, for example in a long table.
3. Use the icon from CSS
A CSS mask turns any monotone SVG into a shape filled with background-color, so the icon follows your text color while its markup stays out of the HTML:
.icon-home {
display: inline-block;
width: 1em;
height: 1em;
background-color: currentColor;
-webkit-mask: url("https://iconyz.com/api/public/svg/lucide/house.svg") no-repeat center / contain;
mask: url("https://iconyz.com/api/public/svg/lucide/house.svg") no-repeat center / contain;
}<span class="icon-home" aria-hidden="true"></span>The CSS tab in each icon panel generates this rule with the SVG embedded as a data URI, so it works without any external request. Use masks for monotone icons only: a mask keeps the shape and discards the icon's own colors. For multicolor icons, use background-image instead.
4. React and other JSX frameworks
JSX needs camelCase attributes (strokeWidth, not stroke-width) and passes props through. The React tab in each icon panel produces a ready-made component:
export function HouseIcon(props) {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em"
viewBox="0 0 24 24" {...props}>
<path fill="none" stroke="currentColor" strokeWidth={2} d="…" />
</svg>
);
}
// Usage
<HouseIcon className="text-blue-600" style={{ fontSize: 20 }} aria-hidden="true" />Because the size is 1em, the icon scales with font-size, and because the color is currentColor, utility classes such as Tailwind's text-* recolor it. Keep one file per icon, or group icons in a module, so your bundler can tree-shake the ones you don't import. The same component works in Preact, and the Solid tab gives the Solid variant.
5. Vue and Svelte
In Vue, save the icon as a single-file component. Attributes you pass, such as class, fall through to the root <svg>:
<!-- HouseIcon.vue -->
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-width="2" d="…" />
</svg>
</template>Svelte works the same way: a .svelte file that contains the SVG markup with {...$$props} on the root element. Both are available as tabs in the icon panel.
Size and color
- Size with
1em. Setting width and height to1emmakes an icon match the text next to it. Changefont-sizeto resize it. - Keep the viewBox. The
viewBoxdefines the drawing's coordinate system. Removing it breaks scaling; resize with width and height instead. - Match the grid. Icons drawn on a 24px grid look sharpest at 24px, 48px or other multiples. At 18px or 20px, thin strokes may look slightly blurred.
- Color monotone icons with
color. WithcurrentColor, one CSS rule handles normal, hover and dark-mode states. - Multicolor icons keep their palette. Emoji, flags and logos have colors built in. Recolor them only when the license allows modification, and never alter brand logos.
Accessibility
Decide whether the icon carries meaning. Decorative icons next to a text label should be hidden from screen readers, and icons that stand alone need a text alternative:
<!-- Decorative: the button already has a text label -->
<button><svg aria-hidden="true" …>…</svg> Save</button>
<!-- Icon-only button: label the button, hide the icon -->
<button aria-label="Close"><svg aria-hidden="true" …>…</svg></button>
<!-- Meaningful image -->
<img src="…/triangle-alert.svg" alt="Warning">Also check contrast: icons that convey information need a contrast ratio of at least 3:1 against their background under WCAG 2.2.
Which method should you use?
| Method | Style with CSS | Extra request | Best for |
|---|---|---|---|
| <img> | No (color via URL) | Yes, cached | Content images, emails, Markdown, quick prototypes |
| Inline SVG | Fully | No | A handful of icons that need hover states or animation |
| CSS mask | Color and size | No with a data URI | Icon classes in CSS-heavy sites and design systems |
| Components | Fully | No, bundled | React, Vue, Svelte and Solid apps |
Ready to start? Search all icon sets, or browse popular ones such as Lucide, Tabler Icons and Material Design Icons. Before shipping, check the set's license; the icon licenses guide explains what each one requires.