Skip to content

Icon components on demand for almost 300k icons, rendered as SVG + CSS

License

Notifications You must be signed in to change notification settings

iconify/iconify-unplugin

Repository files navigation

Iconify Unplugin

This library generates icon components on demand. It works with multiple frameworks and bundlers.

It uses Iconify as source for icons, which offers over 200 open source icon sets with almost 300k icons.

Usage example

<script setup>
import BellIcon from '/~iconify/mdi-light/bell';
</script>
<template>
	<BellIcon height="1em" />
</template>

SVG with CSS

The big difference from other solutions is, icons are split into SVG and CSS parts.

Instead of rendering full SVG like this:

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
  <path fill="currentColor" d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2" />
</svg>

Iconify Unplugin renders smaller SVG:

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
  <path class="mdi-account-box" />
</svg>

and moves all shapes to CSS:

.mdi-account-box {
	fill: currentColor;
	d: path(
		'M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2'
	);
}

See SVG + CSS for details.

Why is this better?

  • Reduces HTML size, especially noticesable when the same icon is used multiple times.
  • CSS is cached, so icon content is cached by browser instead of being included in HTML.

Plugin uses hashing to generate unique class names. This prevents duplication and avoids collissions.

Safari browser

There is one issue with rendering SVG+CSS: currently Safari browser does not support d attribute for <path /> in CSS.

To work around this issue, components include dynamic fallback, which is loaded and rendered only for outdated browsers.

See solving Safari fallback for SVG+CSS.

In future, when Safari will finally join the modern browsers (hopefully soon because Safari Technology Preview supported this since 2024), fallback can be removed. This will make it possible to add support for more frameworks and render icons as raw HTML strings, not components.

Fallback packages

To support Safari browser, you need to install the following dev dependencies:

  • For Vue: @iconify/css-vue
  • For Svelte: @iconify/css-svelte
  • For React and Preact: @iconify/css-react

There are no fallback components for other frameworks. If you are not using frameworks listed above, your options are:

  • Ignore Safari users (bad option).
  • Render full SVG instead of SVG+CSS (see plugin options below).

Compilers

Iconify Unplugin supports several compilers.

Compilers with a fallback for Safari browser:

  • vue - generates Vue 3 components.
  • svelte - generates Svelte 5 components (uses runes).
  • react - generates React components.
  • preact - generates Preact components.

Compilers without a fallback, so icons will work only in modern browsers:

  • raw - generates icon as string, can be used in with framework (see vite-vue and vite-svelte examples for usage).

Installation

Installation depends on bundler and framework you are using.

See examples in examples directory for... examples.

First step is to install @iconify/unplugin as a dependency.

Vite

For Vite, open vite.config.js, add import statement for plugin and plugin entry in plugins property.

Example configuration:

import { defineConfig } from 'vite';
import Icons from '@iconify/unplugin/vite';

export default defineConfig({
	plugins: [
		Icons({
			// Change to 'vue' for Vue, 'react' for React, etc...
			compiler: 'svelte',
		}),
	],
});

Syntax for other bundlers is similar to example above:

  • Replace "vite" with bundler name. Supported bundlers: "esbuild", "farm", "rollup", "rspack", "webpack".
  • Add plugin to plugins list. Plugin options are the same for all bundlers.

Plugin options

Plugin accepts the following options:

  • compiler: default "compiler" value for icons.
  • namespace: change URL from "iconify" to something else, allowing you to use multiple instances of plugin with different options.
  • mode: rendering mode, default is "svg+css". Supported values are "svg+css" and "svg" to render full SVG.
  • css: rendering mode for stylesheet, default is "import".

See src/plugin/types/options.ts for full list of options.

Most of these options are used in examples. See "examples" directory.

Some of these options can be overwritten for each icon by adding URL parameters. If both URL parameter and config value are set, URL parameter is used.

CSS modes

Plugin supports several modes for rendering SVG+CSS icons, which can be set in "css" option or URL parameter:

  • "import": styles are split in separate files, imported from package. This reduces duplication.
  • "module": uses CSS modules. This is not advised because it generates much longer class names without providing any benefit. However, some frameworks, such as Next.js and Qwik, intentionally do not support importing css files, so this is an option if you are using one of those frameworks.
  • "embed": embeds CSS in SVG using <style> tag.

Default value is "import".

Icon sets

Plugin does not include icons.

If you want access to all icons, add @iconify/json as a dev dependency.

If you want access to only several icon sets, add @iconify-json/{prefix} dependencies for each icon set (replace {prefix} with icon set prefix).

Plugin can also load icons from Iconify API and cache it, but this could be slow, so better install dependencies mentioned above.

Usage

Import icon component from /~iconify/{prefix}/{name}, where:

  • {prefix} is icon set prefix, such as "mdi"
  • {name} is icon name, such as "home"

See Iconify icon sets for all icons. Select icon and you'll see an option to copy icon name.

Then use that icon as component.

Additionally, instead of /~iconify/ prefix for icon names, you can use:

  • virtual:iconify/ - not supported by webpack
  • /virtual:iconify/ - not supported by webpack

You can also change iconify part to anything else by setting namespace option to plugin (see examples in examples directory), which can be used to run multiple instances of plugin with different options.

Vue example

<script setup>
import BellIcon from '/~iconify/mdi-light/bell';
</script>
<template>
	<BellIcon height="1em" />
</template>

Svelte example

<script>
import BellIcon from '/~iconify/mdi-light/bell';
</script>

<BellIcon height="1em" />

React example

import BellIcon from '/~iconify/mdi-light/bell';

function Test() {
	return <BellIcon height="1em" />;
}

Parameters

You can add parameters to component URL:

import BellIcon from '/~iconify/mdi-light/bell?height=1em&compiler=vue';

Supported parameters:

  • square=true - makes icon's viewBox square.
  • width and height - sets icon size: height=1em.
  • size sets both width and height: size=1em.
  • fallback overrides fallback icon name for Safari browser. Set it to an empty string to disable Safari fallback.
  • compiler overrides default compiler for icon.

Size parameters

If you do not specify any of size parameters, generated icon component will accept width and height properties, which allow you to set size dynamically.

To set a fixed size, you can use width, height or size parameters:

You do not need to set multiple size properties, one is enough. For example, if you set height=1em, width will be automatically calculated using icon's width/height ratio.

// All examples are identical because icon is square
import BellIcon from '/~iconify/mdi-light/bell?height=1em';
import BellIcon from '/~iconify/mdi-light/bell?width=1em';
import BellIcon from '/~iconify/mdi-light/bell?size=1em';

If you set a size parameter, generated component will have hardcoded size and will no longer accept width and height properties.

That means, this will no longer work as expected:

<script setup>
import BellIcon from '/~iconify/mdi-light/bell?height=1em';
</script>
<template>
	<!-- Icon will have 1em height because it is set in import URL, property "height" is ignored -->
	<BellIcon height="2em" />
</template>

Color

To change icon color, change text color.

You can do it in CSS, you can use inline style.

<script setup>
import BellIcon from '/~iconify/mdi-light/bell?size=1em';
</script>
<template>
	<BellIcon style="color: red;" />
</template>

Issues

Possible issues:

Cache warning

Plugin stores generated assets in cache in file system. By default, cache is stored in node_modules/.iconify-unplugin.

If for some reason that directory is not writable, you can set custom cache directory in cacheDir option in plugin.

Licence

Iconify Unplugin package is licensed under MIT license.

SPDX-License-Identifier: MIT

© 2025-PRESENT Vjacheslav Trushkin

About

Icon components on demand for almost 300k icons, rendered as SVG + CSS

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

  •  

Packages

No packages published