ICONYZ
English

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 to 1em makes an icon match the text next to it. Change font-size to resize it.
  • Keep the viewBox. The viewBox defines 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. With currentColor, 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?

MethodStyle with CSSExtra requestBest for
<img>No (color via URL)Yes, cachedContent images, emails, Markdown, quick prototypes
Inline SVGFullyNoA handful of icons that need hover states or animation
CSS maskColor and sizeNo with a data URIIcon classes in CSS-heavy sites and design systems
ComponentsFullyNo, bundledReact, 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.