Access thousands of icons as components on-demand universally
npm install unplugin-icons
Access thousands of icons as components on-demand universally.
- ๐ Universal
- ๐คน Any icon sets - ~150 popular sets with over 200,000 icons, logos, emojis, etc. Powered by Iconify.
- ๐ฆ Major build tools - Vite, Webpack, Rollup, Nuxt, Rspack, etc. Powered by unplugin.
- ๐ Major frameworks - Vanilla, Web Components, React, Vue 3, Solid, Svelte, and more. Contribute.
- ๐ฑ Any combinations of them!
- โ๏ธ On-demand - Only bundle the icons you really use, while having all the options.
- ๐จ SSR / SSG friendly - Ship the icons with your page, no more FOUC.
- ๐ Stylable - Change size, color, or even add animations as you would with styles and classes.
- ๐ฅ Custom icons - load your custom icons to get universal integrations at ease.
- ๐ฒ Auto Importing - Use icons as components directly in your template.
- ๐ฆพ TypeScript support.
- ๐ Browse Icons
๐ก Story behind this tool: Journey with Icons Continues - a blog post by Anthony |
> vite-plugin-icons has been renamed to unplugin-icons, see the migration guide
Import icons using the convention ~icons/{collection}/{icon} and use them as components. Auto importing is also supported.
React Example:
``jsx
import IconAccessibility from '~icons/carbon/accessibility'
import IconAccountBox from '~icons/mdi/account-box'
function App() {
return (
Vue Example:
`vue
`Installation
> Note: This package is ESM-only. Make sure your project uses ES modules (
"type": "module" in package.json or .mjs file extensions).$3
`bash
npm i -D unplugin-icons
`$3
We use Iconify as the icons data source (supports 100+ icon sets).
> [!TIP]
> โจ VS Code Users: Install the Iconify IntelliSense extension for inlay preview, auto-completion, and hover information.
Option A: Install Full Collection (Recommended for flexibility)
`bash
npm i -D @iconify/json
`This installs all icon sets (~120MB). Only icons you actually use will be bundled in production.
Option B: Install Individual Icon Sets
Install only the icon sets you need:
`bash
npm i -D @iconify-json/mdi @iconify-json/carbon
`Option C: Auto Install (Experimental)
Let
unplugin-icons automatically install icon sets when you import them:`ts
Icons({
autoInstall: true, // Auto-detects npm/yarn/pnpm
})
`Examples
Check out the playgrounds page to try examples online in StackBlitz.
Available examples:
- Vite + Vue 3
- Vite + React
- Next.js
- Nuxt 4
- SvelteKit
- Astro
- And more...
Configuration
This section covers how to configure
unplugin-icons for different build tools and frameworks.$3
Vite
`ts
// vite.config.ts
import Icons from 'unplugin-icons/vite'export default defineConfig({
plugins: [
Icons({ / options / }),
],
})
`
Rollup
`ts
// rollup.config.js
import Icons from 'unplugin-icons/rollup'export default {
plugins: [
Icons({ / options / }),
],
}
`
Webpack
`ts
// webpack.config.mjs
import Icons from 'unplugin-icons/webpack'export default {
/ ... /
plugins: [
Icons({ / options / }),
],
}
`
Nuxt
Nuxt 2 and Nuxt Bridge
`ts
// nuxt.config.ts
export default {
buildModules: [
['unplugin-icons/nuxt', { / options / }],
],
}
`Nuxt 3/4
`ts
// nuxt.config.ts
export default defineNuxtConfig({
modules: [
['unplugin-icons/nuxt', { / options / }]
],
})
`Or work with unplugin-vue-components resolvers
`ts
import IconsResolver from 'unplugin-icons/resolver'
import ViteComponents from 'unplugin-vue-components/vite'// nuxt.config.ts
export default defineNuxtConfig({
modules: [
'unplugin-icons/nuxt',
],
vite: {
plugins: [
ViteComponents({
resolvers: [
IconsResolver({/ options /}),
],
}),
],
},
})
`See the Nuxt example for a working example project.
Rspack
`ts
import Icons from 'unplugin-icons/rspack'// rspack.config.mjs
export default defineConfig({
plugins: [
// ...
Icons({/ options /}),
]
})
`
Vue CLI
> Note: This package is ESM-only. You need to use
vue.config.mjs with ES module syntax (requires @vue/cli-service ^5.0.8).`ts
// vue.config.mjs
import Icons from 'unplugin-icons/webpack'export default {
configureWebpack: {
plugins: [
Icons({ / options / }),
],
},
}
`
SvelteKit
Add to your
vite.config.ts:`ts
import { sveltekit } from '@sveltejs/kit/vite'
import Icons from 'unplugin-icons/vite'
import { defineConfig } from 'vite'export default defineConfig({
plugins: [
sveltekit(),
Icons({
compiler: 'svelte',
})
]
})
`Check instructions in the
Frameworks -> Svelte section below if you faced module import errors.See the SvelteKit example for a working example project.
Svelte + Vite
Svelte support requires the
@sveltejs/vite-plugin-svelte plugin:
`shell
npm i -D @sveltejs/vite-plugin-svelte
`Add to your
vite.config.ts:`ts
import { svelte } from '@sveltejs/vite-plugin-svelte'
import Icons from 'unplugin-icons/vite'
import { defineConfig } from 'vite'export default defineConfig({
plugins: [
svelte(),
Icons({
compiler: 'svelte',
}),
],
})
`Check instructions in the
Frameworks -> Svelte section below if you faced module import errors.See the Svelte + Vite example for a working example project.
Next.js
> Note: This package is ESM-only. You need to use
next.config.mjs with ES module syntax.Add to your
next.config.mjs:`ts
// next.config.mjs
import Icons from 'unplugin-icons/webpack'/* @type {import('next').NextConfig} /
export default {
reactStrictMode: true,
webpack(config) {
config.plugins.push(
Icons({
compiler: 'jsx',
jsx: 'react'
})
)
return config
}
}
`Check instructions in the
Frameworks -> React section below if you faced module import errors.โ ๏ธ Warning: to import an icon is necessary to explicitly add the
.jsx extension to the import path, so that Next.js knows how to load it, by example:`ts
import IconArrowRight from '~icons/dashicons/arrow-right.jsx';
// ^-- write .jsx to avoid
// https://github.com/antfu/unplugin-icons/issues/103
// ...some code later
`See the Next.js example for a working example project.
esbuild
`ts
// esbuild.config.js
import { build } from 'esbuild'
import Icons from 'unplugin-icons/esbuild'build({
/ ... /
plugins: [
Icons({
/ options /
}),
],
})
`
Astro
`ts
// astro.config.mjs
import { defineConfig } from 'astro/config'
import Icons from 'unplugin-icons/vite'// https://astro.build/config
export default defineConfig({
vite: {
plugins: [
Icons({
compiler: 'astro',
}),
],
},
})
`See the Astro example for a working example project.
Astro + Vue
Required @astrojs/vue installed.
`ts
import Vue from '@astrojs/vue'
// astro.config.mjs
import { defineConfig } from 'astro/config'
import Icons from 'unplugin-icons/vite'// https://astro.build/config
export default defineConfig({
integrations: [
Vue(),
],
vite: {
plugins: [
Icons({
compiler: 'vue3',
}),
],
},
})
`See the Astro + Vue example for a working example project.
$3
Configure the
compiler option based on your framework. Some frameworks may require additional peer dependencies.
Vue 3
Configuration:
`ts
Icons({ compiler: 'vue3' })
`Peer Dependency:
> Note: As of Vue 3.2.13+,
@vue/compiler-sfc is included in the main vue package, so no additional installation is needed.If you're using an older version:
`bash
npm i -D @vue/compiler-sfc
`TypeScript Support:
Add to your
tsconfig.json:`jsonc
{
"compilerOptions": {
"types": [
"unplugin-icons/types/vue"
]
}
}
`See the Vue 3 example for a complete setup.
React
Configuration:
`ts
Icons({ compiler: 'jsx', jsx: 'react' })
`Peer Dependencies:
`bash
npm i -D @svgr/core @svgr/plugin-jsx
`TypeScript Support:
Add to your
tsconfig.json:`jsonc
{
"compilerOptions": {
"types": [
"unplugin-icons/types/react"
]
}
}
`See the React example for a complete setup.
Preact
Configuration:
`ts
Icons({ compiler: 'jsx', jsx: 'preact' })
`Peer Dependencies:
`bash
npm i -D @svgr/core @svgr/plugin-jsx
`TypeScript Support:
Add to your
tsconfig.json:`jsonc
{
"compilerOptions": {
"types": [
"unplugin-icons/types/preact"
]
}
}
`See the Preact example for a complete setup.
Solid
Configuration:
`ts
Icons({ compiler: 'solid' })
`TypeScript Support:
Add to your
tsconfig.json:`jsonc
{
"compilerOptions": {
"types": [
"unplugin-icons/types/solid"
]
}
}
`See the Solid example for a complete setup.
Svelte
Configuration:
`ts
Icons({ compiler: 'svelte' })
`TypeScript Support:
For SvelteKit, add to
src/app.d.ts:`ts
import 'unplugin-icons/types/svelte'
`For Svelte + Vite, add to
src/vite-env.d.ts:`ts
///
///
///
`For Svelte 4, use:
`ts
///
`For Svelte 3, use:
`ts
///
`See the Svelte example for a complete setup.
Astro
Configuration:
`ts
Icons({ compiler: 'astro' })
`TypeScript Support:
Add to your
tsconfig.json:`jsonc
{
"compilerOptions": {
"types": [
"unplugin-icons/types/astro"
]
}
}
`See the Astro example for a complete setup.
Astro + Vue
Configuration:
`ts
Icons({ compiler: 'vue3' })
`Requirements:
Requires @astrojs/vue to be installed.
TypeScript Support:
Add to your
tsconfig.json:`jsonc
{
"compilerOptions": {
"types": [
"unplugin-icons/types/vue"
]
}
}
`See the Astro + Vue example for a complete setup.
Qwik
Option 1: Native Qwik Compiler (Recommended)
Configuration:
`ts
Icons({ compiler: 'qwik' })
`Peer Dependency:
`bash
npm i -D @svgx/core
`Option 2: JSX Compiler
Configuration:
`ts
Icons({ compiler: 'jsx', jsx: 'qwik' })
`Peer Dependencies:
`bash
npm i -D @svgr/core @svgr/plugin-jsx
`TypeScript Support:
Add to your
tsconfig.json:`jsonc
{
"compilerOptions": {
"types": [
"unplugin-icons/types/qwik"
]
}
}
`See the Qwik example for a complete setup.
Ember
Configuration:
`ts
Icons({ compiler: 'ember' })
`Build Tool Support:
Ember works with either Webpack or Vite.
For Vite applications, add to
vite.config.mjs:`ts
import { ember, extensions } from '@embroider/vite'
import { babel } from '@rollup/plugin-babel'
import Icons from 'unplugin-icons/vite'
import { defineConfig } from 'vite'export default defineConfig({
plugins: [
ember(),
Icons({
compiler: 'ember',
}),
babel({
babelHelpers: 'runtime',
extensions,
}),
],
})
`TypeScript Support:
Add to your
tsconfig.json:`jsonc
{
"compilerOptions": {
"types": [
"unplugin-icons/types/ember"
]
}
}
`Ember + Webpack
Assuming your app was generated with
--embroider, or manually migrated to embroider following the instructions on the old embroider readmeAdd the Icon plugin to the webpack plugins array in
ember-cli-build.js:`ts
import { compatBuild } from '@embroider/compat'
import Icons from 'unplugin-icons/webpack'return compatBuild(app, Webpack, {
packagerOptions: {
webpackConfig: {
plugins: [
Icons({
compiler: 'ember',
}),
],
},
},
// ...other options
`See the Ember (with Webpack) or Ember vite example for a working example project.
Raw SVG Import
> Available from
v0.13.2+Import icons as raw SVG strings by adding
?raw to the import path. Useful for embedding SVG directly in HTML templates.Example (Vue 3):
`vue
import RawMdiAlarmOff from '~icons/mdi/alarm-off?raw&width=4em&height=4em'
{{ RawMdiAlarmOff }}
import RawMdiAlarmOff2 from '~icons/mdi/alarm-off?raw&width=1em&height=1em'
{{ RawMdiAlarmOff2 }}
`Custom Icons
Load your own custom icons and use them with the same universal API.
`ts
import { promises as fs } from 'node:fs'// loader helpers
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
Icons({
customCollections: {
// key as the collection name
'my-icons': {
account: '',
// load your custom icon lazily
settings: () => fs.readFile('./path/to/my-icon.svg', 'utf-8'),
/ ... /
},
'my-other-icons': async (iconName) => {
// your custom loader here. Do whatever you want.
// for example, fetch from a remote server:
return await fetch(
https://example.com/icons/${iconName}.svg).then(res => res.text())
},
// a helper to load icons from the file system
// files under ./assets/icons with .svg extension will be loaded as it's file name
// you can also provide a transform callback to change each icon (optional)
'my-yet-other-icons': FileSystemIconLoader(
'./assets/icons',
svg => svg.replace(/^ ),
},
})
`Then use as
`ts
import IconAccount from '~icons/my-icons/account'
import IconFoo from '~icons/my-other-icons/foo'
import IconBar from '~icons/my-yet-other-icons/bar'
`> ๐ก SVG Authoring Tips:
> - To make your icons color adaptable, set
fill="currentColor" or stroke="currentColor" in your SVG.
> - Leave the height and width unspecified, we will set them for you.$3
When using auto-importing, register your custom collection names:
`ts
IconResolver({
customCollections: [
'my-icons',
'my-other-icons',
'my-yet-other-icons',
],
})
`See the Vue 3 example for a complete setup.
$3
Load icons from third-party packages that follow the Iconify format.
Requirements:
External packages must include an
icons.json file in IconifyJSON format. See Exporting icon set as JSON package for details.For example, you can use
an-awesome-collection or @my-awesome-collections/some-collection to load your custom or third party icons:
`ts
// loader helpers
import { ExternalPackageIconLoader } from 'unplugin-icons/loaders'Icons({ customCollections: ExternalPackageIconLoader('my-awesome-collection') })
`When using with resolvers for auto-importing, remember you will need to tell it your custom collection names:
`ts
IconResolver({
customCollections: [
'my-awesome-collection',
],
})
`You can also combine it with
FileSystemIconLoader or with other custom icon loaders:
`ts
// loader helpers
import { ExternalPackageIconLoader, FileSystemIconLoader } from 'unplugin-icons/loaders'Icons({
customCollections: {
...ExternalPackageIconLoader('an-awesome-collection'),
...ExternalPackageIconLoader('@my-awesome-collections/some-collection'),
...ExternalPackageIconLoader('@my-awesome-collections/some-other-collection'),
'my-yet-other-icons': FileSystemIconLoader(
'./assets/icons',
svg => svg.replace(/^ ),
},
})
`See the Vue 3 example for a complete setup.
Icon Customization
Customize individual icons or entire collections using
iconCustomizer in your config or query parameters when importing.Precedence: Query params >
iconCustomizer > default configurationWorks with all icon sources: custom loaders, inlined collections, and Iconify collections.
For example, you can configure
iconCustomizer to change all icons for a collection or individual icons on a collection:`ts
import { promises as fs } from 'node:fs'// loader helpers
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
Icons({
customCollections: {
// key as the collection name
'my-icons': {
account: '',
// load your custom icon lazily
settings: () => fs.readFile('./path/to/my-icon.svg', 'utf-8'),
/ ... /
},
'my-other-icons': async (iconName) => {
// your custom loader here. Do whatever you want.
// for example, fetch from a remote server:
return await fetch(
https://example.com/icons/${iconName}.svg).then(res => res.text())
},
// a helper to load icons from the file system
// files under ./assets/icons with .svg extension will be loaded as it's file name
// you can also provide a transform callback to change each icon (optional)
'my-yet-other-icons': FileSystemIconLoader(
'./assets/icons',
svg => svg.replace(/^ ),
},
iconCustomizer(collection, icon, props) {
// customize all icons in this collection
if (collection === 'my-other-icons') {
props.width = '4em'
props.height = '4em'
}
// customize this icon in this collection
if (collection === 'my-icons' && icon === 'account') {
props.width = '6em'
props.height = '6em'
}
// customize this @iconify icon in this collection
if (collection === 'mdi' && icon === 'account') {
props.width = '2em'
props.height = '2em'
}
},
})
`or you can use
query params to apply to individual icons:`vue
`See the Vue 3 example for a complete implementation.
Global Icon Transformation
Apply transformations to all custom icons during loading. Useful for adding default attributes like
fill="currentColor".
`ts
Icons({
customCollections: {
// key as the collection name
'my-icons': {
account: '',
/ ... /
},
},
transform(svg, collection, icon) {
// apply fill to this icon on this collection
if (collection === 'my-icons' && icon === 'account')
return svg.replace(/^`Advanced Custom Icon Set Cleanup
When using this plugin with your custom icons, consider using a cleanup process similar to that done by Iconify for any icons sets. All the tools you need are available in Iconify Tools.
You can check this repo, using
unplugin-icons on a SvelteKit project: https://github.com/iconify/tools/tree/main/%40iconify-demo/unplugin-svelte.Read Cleaning up icons article from Iconify for more details.
Migration from
vite-plugin-iconsIf you're upgrading from
vite-plugin-icons, follow these steps:1. Update
package.json:`diff
{
"devDependencies": {
- "vite-plugin-icons": "*",
+ "unplugin-icons": "^0.7.0",
}
}
`2. Update your config file:
`diff
import Components from 'unplugin-vue-components/vite'
- import Icons, { ViteIconsResolver } from 'vite-plugin-icons'
+ import Icons from 'unplugin-icons/vite'
+ import IconsResolver from 'unplugin-icons/resolver'export default {
plugins: [
Vue(),
Components({
resolvers: [
IconsResolver()
],
}),
Icons(),
],
}
`3. Update import paths:
`diff
- import IconComponent from 'virtual:vite-icons/collection/name'
+ import IconComponent from '~icons/collection/name'
`> Note: The
virtual:icons prefix still works in Vite, but ~icons is recommended for consistency across all build tools.Options
Configure default styling and behavior for all icons:
`ts
Icons({
// Icon sizing
scale: 1.2, // Scale factor relative to 1em (default: 1.2)
// Default styling
defaultStyle: '', // CSS styles applied to all icons
defaultClass: '', // CSS classes applied to all icons
// Compiler configuration
compiler: null, // Framework compiler: 'vue3', 'jsx', 'svelte', 'solid', etc.
jsx: 'react', // JSX framework: 'react' or 'preact' (when compiler: 'jsx')
// Custom collections
customCollections: {}, // See Custom Icons
// Advanced
iconCustomizer: () => {}, // See Icon Customization
transform: undefined, // See Global Icon Transformation
autoInstall: false, // Auto-install icon sets on import
})
`Auto Importing
Vue 3
unplugin-vue-componentsFor example in Vite:
`ts
// vite.config.ts
import Vue from '@vitejs/plugin-vue'
import IconsResolver from 'unplugin-icons/resolver'
import Icons from 'unplugin-icons/vite'
import Components from 'unplugin-vue-components/vite'export default {
plugins: [
Vue(),
Components({
resolvers: [
IconsResolver(),
],
}),
Icons(),
],
}
`Then you can use any icons as you want without explicit importing. Only the used icons will be bundled.
`html
`
React & Solid
unplugin-auto-importFor example in Vite:
`ts
// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import IconsResolver from 'unplugin-icons/resolver'
import Icons from 'unplugin-icons/vite'export default {
plugins: [
AutoImport({
resolvers: [
IconsResolver({
prefix: 'Icon',
extension: 'jsx',
}),
],
}),
Icons({
compiler: 'jsx', // or 'solid'
}),
],
}
`Then you can use any icons with the prefix
Icon as you want without explicit importing. Type declarations will be generated on the fly.`js
export function Component() {
return (
)
}
`$3
Icons are auto-imported following this naming pattern:
`
{prefix}-{collection}-{icon}
`-
prefix: Component name prefix (default: i)
- collection: Iconify collection ID (e.g., mdi, carbon, fa-solid)
- icon: Icon name (kebab-case)Custom Prefix:
`ts
IconsResolver({
prefix: 'icon', // Use 'icon' instead of 'i'
})
``vue
`No Prefix:
`ts
IconsResolver({
prefix: false,
enabledCollections: ['mdi'], // Optional: limit to specific collections
})
``vue
`$3
Create shorter aliases for long collection names:
`ts
IconsResolver({
alias: {
park: 'icon-park', // Use /> instead of />
fas: 'fa-solid', // Use /> instead of />
}
})
`Both the alias and full collection name work:
`vue
``This project is part of my Sponsor Program
MIT License ยฉ 2020-PRESENT Anthony Fu