Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
unplugin-icons
Advanced tools
unplugin-icons is an npm package that provides a convenient way to use icons from various icon sets in your projects. It supports multiple frameworks like Vue, React, and Svelte, and allows you to import icons on-demand, reducing the bundle size.
On-Demand Icon Import
This feature allows you to import only the icons you need, which helps in reducing the bundle size. The code sample demonstrates how to import and use a specific icon from the 'bi' (Boxicons) set in a React component.
import { Icon } from 'unplugin-icons';
import { BiAlarm } from 'unplugin-icons/bi';
const MyComponent = () => (
<div>
<Icon icon={BiAlarm} />
</div>
);
Framework Support
unplugin-icons supports multiple frameworks like Vue, React, and Svelte. The code sample shows how to use an icon in a Vue component.
import { defineComponent } from 'vue';
import { BiAlarm } from 'unplugin-icons/bi';
export default defineComponent({
components: { BiAlarm },
template: '<BiAlarm />'
});
Custom Icon Sets
You can also use custom icon sets with unplugin-icons. The code sample demonstrates how to import and use a custom icon in a React component.
import { Icon } from 'unplugin-icons';
import { MyCustomIcon } from './my-custom-icons';
const MyComponent = () => (
<div>
<Icon icon={MyCustomIcon} />
</div>
);
react-icons is a popular package for including icons in React applications. It supports a wide range of icon libraries and allows for easy integration. Compared to unplugin-icons, react-icons is more focused on React and does not offer the same level of support for other frameworks.
vue-awesome is a package for using Font Awesome icons in Vue applications. It provides a simple way to include and customize Font Awesome icons. Unlike unplugin-icons, vue-awesome is limited to Font Awesome and does not support other icon sets.
svelte-icons is a package for using icons in Svelte applications. It supports multiple icon sets and provides a simple API for including icons. While it offers similar functionality to unplugin-icons, it is specifically designed for Svelte.
Access thousands of icons as components on-demand universally.
💡 Story behind this tool: Journey with Icons Continues - a blog post by Anthony |
vite-plugin-icons
has been renamed tounplugin-icons
, see the migration guide
Import icons names with the convension ~icons/{collection}/{icon}
and use them directly as components. Auto importing is also possible.
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>
)
}
<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>
npm i -D unplugin-icons
We use Iconify as the icons data source (supports 100+ iconsets).
You have two ways to install them:
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).
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({
// expiremental
autoInstall: true
})
It will install the icon set when you import them. The right package manager will be auto-detected (npm
, yarn
or pnpm
).
// vite.config.ts
import Icons from 'unplugin-icons/vite'
export default defineConfig({
plugins: [
Icons({ /* options */ }),
],
})
// rollup.config.js
import Icons from 'unplugin-icons/rollup'
export default {
plugins: [
Icons({ /* options */ }),
],
}
// webpack.config.js
module.exports = {
/* ... */
plugins: [
require('unplugin-icons/webpack')({ /* options */ })
]
}
// nuxt.config.js
export default {
buildModules: [
['unplugin-icons/nuxt', { /* options */ }],
],
}
This module works for both Nuxt 2 and Nuxt Vite
// vue.config.js
module.exports = {
configureWebpack: {
plugins: [
require('unplugin-icons/webpack')({ /* options */ }),
],
},
}
// svelte.config.js
import preprocess from 'svelte-preprocess'
import Icons from 'unplugin-icons/vite'
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess(),
kit: {
// hydrate the <div id="svelte"> element in src/app.html
target: '#svelte',
vite: {
plugins: [
Icons({
compiler: 'svelte',
}),
],
},
},
}
export default config
Check instructions in the Frameworks -> Svelte
section below if you faced module import errors.
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:
// vite.config.js
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.
The unplugin-icons
plugin should be configured on next.config.js
configuration file:
/** @type {import('next').NextConfig} */
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';
// ^-- write `.jsx` to avoid
// https://github.com/antfu/unplugin-icons/issues/103
// ...some code later
<IconArrowRight />
See inside of examples/next
for a working example project.
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 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",
]
}
}
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",
]
}
}
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",
]
}
}
Icons({ compiler: 'solid' })
Type Declarations
// tsconfig.json
{
"compilerOptions": {
"types": [
"unplugin-icons/types/solid",
]
}
}
Icons({ compiler: 'svelte' })
Type Declarations
For Svelte Kit, on src/global.d.ts
file:
/// <reference types="@sveltejs/kit" />
/// <reference types="unplugin-icons/types/svelte" />
For Svelte + Vite, on src/vite-env.d.ts
file:
/// <reference types="svelte" />
/// <reference types="vite/client" />
/// <reference types="unplugin-icons/types/svelte" />
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'
// loader helpers
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
Icons({
customCollections: {
// key as the collection name
'my-icons': {
'account': '<svg><!-- ... --></svg>',
// 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(/^<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"
orstroke="currentColor"
in your SVG.- Leave the
height
andwidth
unspecified, we will set them for you.
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.
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'
// loader helpers
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
Icons({
customCollections: {
// key as the collection name
'my-icons': {
'account': '<svg><!-- ... --></svg>',
// 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(/^<svg /, '<svg fill="currentColor" ')
),
},
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:
<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.
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.
You can set default styling for all icons. The following config shows the default values of each option:
Icons({
scale: 1.2, // Scale of icons against 1em
defaultStyle: '', // Style apply to icons
defaultClass: '', // Class names apply to icons
compiler: null, // 'vue2', 'vue3', 'jsx'
jsx: 'react' // 'react' or 'preact'
})
Use with unplugin-vue-components
For example in Vite:
// vite.config.js
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>
Use with unplugin-auto-import
For example in Vite:
// vite.config.js
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' // 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.
export function Component() {
return (
<div>
<IconCarbonApps />
<IconMdiAccountBox style="font-size: 2em; color: red"/>
</div>
)
}
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, // <--
// this is optional, default enabling all the collections supported by Iconify
enabledCollections: ['mdi']
})
<template>
<mdi-account />
</template>
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
MIT License © 2020-PRESENT Anthony Fu
FAQs
Access thousands of icons as components on-demand universally
We found that unplugin-icons demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.