unplugin-icons
Access thousands of icons as components on-demand universally.
Features
- ๐ Universal
- ๐คน Any icon sets - 100+ popular sets with over 10,000 icons, logos, emojis, etc. Powered by Iconify.
- ๐ฆ Major build tools - Vite, Webpack, Rollup, Nuxt, etc. Powered by unplugin.
- ๐ช Major frameworks - Vanilla, Web Components, React, Vue 3, Vue 2, 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
vite-plugin-icons
has been renamed to unplugin-icons
, see the migration guide
Usage
Import icons names with the convension ~icons/{collection}/{icon}
and use them directly as components. Auto importing is also possible.
React
import IconAccessibility from '~icons/carbon/accessibility'
import IconAccountBox from '~icons/mdi/account-box'
function App() {
return (
<div>
<IconAccessibility />
<IconAccountBox style={{ fontSize: '2em', color: 'red' }}/>
</div>
)
}
Vue
<script setup>
import IconAccessibility from '~icons/carbon/accessibility'
import IconAccountBox from '~icons/mdi/account-box'
</script>
<template>
<icon-accessibility/>
<icon-account-box style="font-size: 2em; color: red"/>
</template>
Install
Plugin
npm i -D unplugin-icons
Icons Data
We use Iconify as the icons data source (supports 100+ iconsets).
You have two ways to install them:
Install Full Collection
npm i -D @iconify/json
@iconify/json
(~120MB) includes all the iconsets from Iconify so you can install once and use any of them as you want (only the icons you actually use will be bundle into the production build).
Install by Icon Set
If you only want to use a few of the icon sets and don't want to download the entire collection, you can also install them individually with @iconify-json/[collection-id]
.
For example, to install Material Design Icons, you can do:
npm i -D @iconify-json/mdi
To boost your workflow, it's also possible to let unplugin-icons
handle that installation by enabling the autoInstall
option.
Icons({
autoInstall: true,
})
It will install the icon set when you import them. The right package manager will be auto-detected (npm
, yarn
or pnpm
).
Configuration
Build Tools
Vite
import Icons from 'unplugin-icons/vite'
export default defineConfig({
plugins: [
Icons({ }),
],
})
Rollup
import Icons from 'unplugin-icons/rollup'
export default {
plugins: [
Icons({ }),
],
}
Webpack
module.exports = {
plugins: [
require('unplugin-icons/webpack')({ }),
],
}
Nuxt
export default {
buildModules: [
['unplugin-icons/nuxt', { }],
],
}
This module works for both Nuxt 2 and Nuxt Vite
Vue CLI
module.exports = {
configureWebpack: {
plugins: [
require('unplugin-icons/webpack')({ }),
],
},
}
Svelte Kit
import adapter from '@sveltejs/adapter-auto'
import preprocess from 'svelte-preprocess'
import Icons from 'unplugin-icons/vite'
const config = {
preprocess: preprocess(),
kit: {
adapter: adapter(),
vite: {
plugins: [
Icons({
compiler: 'svelte',
}),
],
},
},
}
export default config
Check instructions in the Frameworks -> Svelte
section below if you faced module import errors.
Svelte + Vite
Svelte support requires plugin dependency @sveltejs/vite-plugin-svelte
:
npm i -D @sveltejs/vite-plugin-svelte
The unplugin-icons
plugin should be configured on vite.config.js
configuration file:
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import Icons from 'unplugin-icons/vite'
export default defineConfig({
plugins: [
svelte(),
Icons({
compiler: 'svelte',
}),
],
})
Check instructions in the Frameworks -> Svelte
section below if you faced module import errors.
Next.js
The unplugin-icons
plugin should be configured on next.config.js
configuration file:
module.exports = {
reactStrictMode: true,
webpack(config) {
config.plugins.push(
require('unplugin-icons/webpack')({
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:
import IconArrowRight from '~icons/dashicons/arrow-right.jsx';
<IconArrowRight />
See inside of examples/next
for a working example project.
esbuild
import { build } from 'esbuild'
build({
plugins: [
require('unplugin-icons/esbuild')({
}),
],
})
Frameworks
Vue 3
Vue 3 support requires peer dependency @vue/compiler-sfc
:
npm i -D @vue/compiler-sfc
Icons({ compiler: 'vue3' })
Type Declarations
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/vue",
]
}
}
Vue 2
Vue 2 support requires peer dependency vue-template-compiler
:
npm i -D vue-template-compiler
Icons({ compiler: 'vue2' })
Type Declarations
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/vue",
]
}
}
React
JSX support requires peer dependency @svgr/core
:
npm i -D @svgr/core
Icons({ compiler: 'jsx', jsx: 'react' })
Type Declarations
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/react",
]
}
}
Preact
JSX support requires peer dependency @svgr/core
:
npm i -D @svgr/core
Icons({ compiler: 'jsx', jsx: 'preact' })
Type Declarations
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/preact",
]
}
}
Solid
Icons({ compiler: 'solid' })
Type Declarations
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/solid",
]
}
}
Svelte
Icons({ compiler: 'svelte' })
Type Declarations
For Svelte Kit, on src/app.d.ts
file:
For Svelte + Vite, on src/vite-env.d.ts
file:
Use RAW compiler from query params
From v0.13.2
you can also use raw
compiler to access the svg
icon and use it on your html templates, just add raw
to the icon query param.
For example, using vue3
:
<script setup lang='ts'>
import RawMdiAlarmOff from '~icons/mdi/alarm-off?raw&width=4em&height=4em'
import RawMdiAlarmOff2 from '~icons/mdi/alarm-off?raw&width=1em&height=1em'
</script>
<template>
<!-- raw example -->
<pre>
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 }}
</pre>
<!-- svg example -->
<span v-html="RawMdiAlarmOff" />
<span v-html="RawMdiAlarmOff2" />
</template>
Custom Icons
From v0.11
, you can now load your own icons!
From v0.13
you can also provide a transform callback to FileSystemIconLoader
.
import { promises as fs } from 'fs'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
Icons({
customCollections: {
'my-icons': {
account: '<svg><!-- ... --></svg>',
settings: () => fs.readFile('./path/to/my-icon.svg', 'utf-8'),
},
'my-other-icons': async (iconName) => {
return await fetch(`https://example.com/icons/${iconName}.svg`).then(res => res.text())
},
'my-yet-other-icons': FileSystemIconLoader(
'./assets/icons',
svg => svg.replace(/^<svg /, '<svg fill="currentColor" '),
),
},
})
Then use as
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.
Use with Resolver
When using with resolvers for auto-importing, you will need to tell it your custom collection names:
IconResolver({
customCollections: [
'my-icons',
'my-other-icons',
'my-yet-other-icons',
],
})
See the Vue 3 + Vite example.
Icon customizer
From v0.13
you can also customize each icon using iconCustomizer
configuration option or using query params when importing them.
The query
param will take precedence over iconCustomizer
and iconCustomizer
over configuration
.
The iconCustomizer
and query
params will be applied to any collection, that is, for each icon from custom
loader, inlined
on customCollections
or from @iconify
.
For example, you can configure iconCustomizer
to change all icons for a collection or individual icons on a collection:
import { promises as fs } from 'fs'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
Icons({
customCollections: {
'my-icons': {
account: '<svg><!-- ... --></svg>',
settings: () => fs.readFile('./path/to/my-icon.svg', 'utf-8'),
},
'my-other-icons': async (iconName) => {
return await fetch(`https://example.com/icons/${iconName}.svg`).then(res => res.text())
},
'my-yet-other-icons': FileSystemIconLoader(
'./assets/icons',
svg => svg.replace(/^<svg /, '<svg fill="currentColor" '),
),
},
iconCustomizer(collection, icon, props) {
if (collection === 'my-other-icons') {
props.width = '4em'
props.height = '4em'
}
if (collection === 'my-icons' && icon === 'account') {
props.width = '6em'
props.height = '6em'
}
if (collection === 'mdi' && icon === 'account') {
props.width = '2em'
props.height = '2em'
}
},
})
or you can use query
params to apply to individual icons:
<script setup lang='ts'>
import MdiAlarmOff from 'virtual:icons/mdi/alarm-off?width=4em&height=4em'
import MdiAlarmOff2 from 'virtual:icons/mdi/alarm-off?width=1em&height=1em'
</script>
<template>
<!-- width=4em and height=4em -->
<mdi-alarm-off />
<!-- width=4em and height=4em -->
<MdiAlarmOff />
<!-- width=1em and height=1em -->
<MdiAlarmOff2 />
</template>
See src/App.vue
component and vite.config.ts
configuration on vite-vue3
example project.
Global Custom Icon Transformation
From version 0.14.2
, when loading your custom icons, you can transform them, for example adding fill
attribute with currentColor
:
Icons({
customCollections: {
'my-icons': {
account: '<svg><!-- ... --></svg>',
},
},
transform(svg, collection, icon) {
if (collection === 'my-icons' && icon === 'account')
return svg.replace(/^<svg /, '<svg fill="currentColor" ')
return svg
},
})
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.
Migrate from vite-plugin-icons
package.json
{
"devDependencies": {
- "vite-plugin-icons": "*",
+ "unplugin-icons": "^0.7.0",
}
}
vite.config.json
import Components from 'unplugin-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(),
],
}
*
- imports usage
- import IconComponent from 'virtual:vite-icons/collection/name'
+ import IconComponent from '~icons/collection/name'
You can still use virtual:icons
prefix in Vite if you prefer, but it's not yet supported in Webpack, we are unifying it as a workaround in the docs.
Options
You can set default styling for all icons.
The following config shows the default values of each option:
Icons({
scale: 1.2,
defaultStyle: '',
defaultClass: '',
compiler: null,
jsx: 'react',
})
Auto Importing
Vue 2 & 3
Use with unplugin-vue-components
For example in Vite:
import Vue from '@vitejs/plugin-vue'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
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.
<template>
<i-carbon-accessibility/>
<i-mdi-account-box style="font-size: 2em; color: red"/>
</template>
React & Solid
Use with unplugin-auto-import
For example in Vite:
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import AutoImport from 'unplugin-auto-import/vite'
export default {
plugins: [
AutoImport({
resolvers: [
IconsResolver({
prefix: 'Icon',
extension: 'jsx',
}),
],
}),
Icons({
compiler: 'jsx',
}),
],
}
Then you can use any icons with the prefix Icon
as you want without explicit importing. Type declarations will be generated on the fly.
export function Component() {
return (
<div>
<IconCarbonApps />
<IconMdiAccountBox style="font-size: 2em; color: red"/>
</div>
)
}
Name Conversion
When using component resolver, you have to follow the name conversion for icons to be properly inferred.
{prefix}-{collection}-{icon}
The collection
field follows Iconify's collection IDs.
By default, the prefix is set to i
while you can customize via config
IconsResolver({
prefix: 'icon',
})
<template>
<icon-mdi-account />
</template>
Non-prefix mode is also supported
IconsResolver({
prefix: false,
enabledCollections: ['mdi'],
})
<template>
<mdi-account />
</template>
Collection Aliases
When using component resolver, you have to use the name of the collection that can be long or redundant: for example,
when using icon-park
collection you need to use it like this <icon-icon-park-abnormal />
.
You can add an alias for any collection to the IconResolver
plugin:
IconsResolver({
alias: {
park: 'icon-park',
fas: 'fa-solid',
}
})
You can use the alias or the collection name, the plugin will resolve both.
Following with the example and configuring the plugin with previous alias
entry, you can now use
<icon-park-abnormal />
or <icon-icon-park-abnormal />
.
This project is part of my Sponsor Program
License
MIT License ยฉ 2020-PRESENT Anthony Fu