vue3 – Import and use Element Plus icons, iconify icons, and local SVG/PNG icons on demand

GitHub Demo address

Online preview

vue3 – Import and use Element Plus icons, iconify icons, and local SVG/PNG icons on demand

      • [GitHub Demo address](https://github.com/iotjin/jh-vue3-admin)
      • [Online preview](https://iotjin.github.io/jh-vue3-admin)
  • 1. iconify plug-in
    • Install
    • use
    • renderings
  • 2. Use iconify through automatic import
    • Install Element Plus
    • Install the automatic import plug-in
    • Install the automatic import Icon plug-in
    • Using Element Plus icons via iconify
    • renderings
    • Element Plus uses Icon like Element UI via UnoCSS
    • renderings
  • 3. SVG local icon
    • renderings
  • 4. Local PNG icon
    • renderings

The icons used in vue projects generally include local png and svg icons, Element icons, and automatic import using third-party libraries iconify’s icon

1. iconify plug-in

Iconify for Vue official documentation

element-plus icon within Iconify

Iconify is an open source icon set and icon management tool. It provides a huge icon library with thousands of commonly used icons covering various themes and styles such as Material Design, Font Awesome, Feather, etc. These icons can be used in vector format (SVG) for various projects such as websites, mobile apps, desktop apps, etc.

Installation

npm install --save-dev @iconify/vue

Use

usage

import {<!-- --> Icon } from '@iconify/vue'

    <!-- https://github.com/iconify/iconify/tree/main/components/vue -->
    <Icon icon="ep:add-location" height="24" />
    <Icon icon="mdi-light:home" width="16" height="16" />
    <Icon icon="mdi-light:home" height="24" />
    <Icon icon="mdi-light:home" height="2em" />
    <Icon icon="mdi-light:home" height="auto" />
    <Icon icon="eva:alert-triangle-fill" color="orange" />
    <Icon icon="eva:alert-triangle-fill" color="#f00" />

    <div>
      <!-- Horizontal flip icon: -->
      <Icon icon="eva:alert-triangle-fill" :h-flip="true" />
      <Icon icon="eva:alert-triangle-fill" :horizontal-flip="true" />
      <Icon icon="eva:alert-triangle-fill" flip="horizontal" />
      <!-- Vertical flip icon -->
      <Icon icon="eva:alert-triangle-fill" :v-flip="true" />
      <Icon icon="eva:alert-triangle-fill" :vertical-flip="true" />
      <Icon icon="eva:alert-triangle-fill" flip="vertical" />
      <!-- Flip icon horizontally and vertically (same as 180 degree rotation): -->
      <Icon icon="eva:alert-triangle-fill" :h-flip="true" :v-flip="true" />
      <Icon icon="eva:alert-triangle-fill" :horizontal-flip="true" :vertical-flip="true" />
      <Icon icon="eva:alert-triangle-fill" flip="horizontal,vertical" />
      <!-- Example of 90 degree rotation: -->
      <Icon icon="eva:alert-triangle-fill" :rotate="1" />
      <!-- <Icon icon="eva:alert-triangle-fill" rotate="90deg" />
      <Icon icon="eva:alert-triangle-fill" rotate="25%" /> -->
    </div>

Renderings

2. Use iconify through automatic import

Install Element Plus

element plus on-demand import official documentation
element plus uses icon official document

You can use the icon icon through element plus in the following two ways (this article uses method 2)
1. You can install the icons-vue component separately through the command npm install @element-plus/icons-vue, and then use
2. You can also automatically import any icon set from iconify by using unplugin-icons and unplugin-auto-import. You can refer to this template.

element plusThe icon icon is generally used through components, such as , or after automatically importing the configuration

npm install element-plus

Install automatic import plug-in

Install two on-demand plug-ins to avoid repeatedly introducing APIs or components on multiple pages
unplugin-auto-import Automatically import APIs on demand, such as: ref, reactive, watch, computed and other APIs
unplugin-vue-components Automatically import components on demand, such as third-party libraries such as Element Plus and custom components in specified directories

npm install -D unplugin-auto-import unplugin-vue-components

Install the automatic import Icon plug-in

Use unplugin-icons and unplugin-auto-import to automatically import icons from iconify

npm i -D unplugin-icons

Configure automatic import in vite.config.ts and create a new /src/types directory to store the automatic import function auto-imports.d.ts and the component’s TS type declaration file components.d.ts

import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import {<!-- --> ElementPlusResolver } from 'unplugin-vue-components/resolvers'

plugins: [
     AutoImport({<!-- -->
      // Automatically import Vue related functions, such as: ref, reactive, toRef, etc.
      imports: ['vue', '@vueuse/core'],
      // imports: ['vue', 'vue-router', 'pinia', '@vueuse/core'],
      eslintrc: {<!-- -->
        enabled: false, // Whether to automatically generate eslint rules. It is recommended to set false after generation and maintain manually.
        filepath: './.eslintrc-auto-import.json', // Specify the file path for automatically importing function eslint rules
        globalsPropValue: true
      },
      resolvers: [
        // Automatically import Element Plus related functions, such as: ElMessage, ElMessageBox... (with styles)
        ElementPlusResolver(),
        IconsResolver({<!-- -->})
      ],
      vueTemplate: true,
      // Configuration file generation location (false: turn off automatic generation)
      dts: false
      // dts: 'src/types/auto-imports.d.ts' // Specify the path to the automatic import function TS type declaration file
    }),

    Components({<!-- -->
      resolvers: [
        // Automatically import Element Plus components
        ElementPlusResolver(),
        // Automatically import icon components
        IconsResolver({<!-- -->
          // @iconify-json/ep is the icon library of Element Plus
          enabledCollections: ['ep']
        })
      ],
      //Specify the location of the custom component (default: src/components)
      dirs: ['src/**/components'],
      // Configuration file location (false: turn off automatic generation)
      dts: false
      // dts: "src/types/components.d.ts",
    }),

    Icons({<!-- -->
      // Automatically install icon library
      autoInstall: true
    }),
]

Add automatic import function eslint rules in .eslintrc.cjs

"extends": [
    "./.eslintrc-auto-import.json"
]

Add automatic import of TS type declaration file in tsconfig.json

{
  "include": ["src/**/*.d.ts"]
}

Run the project npm run dev to see the effect

Use Element Plus icons via iconify

<template>
    <h1>iconify icon:</h1>
    <div>
      <icon1 />
      <!-- <icon2 /> -->
      <icon3 />
    </div>
    
    <div>
      <i-ep-edit />
      <el-icon :size="19.2" color="#409eff">
        <i-ep-edit />
      </el-icon>
    </div>
</template>

<script setup lang="ts">
// element-plus icon
// https://icon-sets.iconify.design/ep/
import icon1 from '~icons/ep/help-filled'
// import { HelpFilled } from '@element-plus/icons-vue'

// others
// https://icon-sets.iconify.design/
// import icon2 from '~icons/mdi/home-clock'
// dynamic icon
// https://icon-sets.iconify.design/line-md/
// https://icon-sets.iconify.design/svg-spinners/
import icon3 from '~icons/line-md/home'
</script>

Renderings

With UnoCSS, Element Plus uses Icon like Element UI

Vue3! How does Element Plus use Icon like Element UI?

UnoCSS official website

UnoCSS is a high-performance and extremely flexible on-the-fly atomic CSS engine for building responsive web and application interfaces. It provides a set of concise, easy-to-use style classes to help developers quickly build beautiful and powerful interfaces.

npm add -D unocss

vite.config.ts configuration

import UnoCSS from 'unocss/vite'
import {<!-- --> presetIcons } from 'unocss'

export default {<!-- -->
  plugins: [
  
    // Configure UnoCSS so that it can directly use the tag <i-ep-edit /> | <el-button icon="i-ep-edit" > edit </el-button>
    // UnoCSS({})
    UnoCSS({<!-- -->
      presets: [
        presetIcons({<!-- -->
          scale: 1.2,
          warn: true
        })
      ],
      // The following configuration is for direct use of the tag <i-ep-edit /> | <el-button icon="i-ep-edit" > edit </el-button>
      variants: [
        {<!-- -->
          match: (s) => {<!-- -->
            if (s.startsWith('i-')) {<!-- -->
              return {<!-- -->
                matcher: s,
                selector: (s) => {<!-- -->
                  return s.startsWith('.') ? `${<!-- -->s.slice(1)},${<!-- -->s}` : s
                }
              }
            }
          }
        }
      ]
    })


  ],
}

main.ts introduces uno.css

import 'uno.css'

Example

 <h2>el-button + icon:</h2>
    <el-button type="primary">
      <el-icon> <i-ep-edit /> </el-icon> New
    </el-button>
    <el-button type="primary" icon="i-ep-edit"> New </el-button>

Renderings

3. SVG local icon

Use the vite-plugin-svg-icons plug-in to use the Iconfont third-party icon library to achieve local SVG icon display
vite-plugin-svg-icons official documentation

npm install -D fast-glob
npm install -D vite-plugin-svg-icons

First specify a path to store svg, such as: src/assets/icons and src/assets/error

Configure the plug-in in vite.config.ts

import {<!-- --> createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'

const resolve = (dir: string) => path.resolve(process.cwd(), dir)

plugins: [
    createSvgIconsPlugin({<!-- -->
      //Specify the icon folder that needs to be cached
      iconDirs: [resolve('src/assets/icons'), resolve('src/assets/error')],
      // iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
      //Specify symbolId format
      symbolId: 'icon-[dir]-[name]'
    }),
]

Introduce the registration script in src/main.ts

import 'virtual:svg-icons-register'

Encapsulate an SVG component for project use
Create the SvgIcon folder in src/components/ and create index.vue

<template>
  <svg aria-hidden="true" class="svg-icon" :style="'width:' + size + ';height:' + size">
    <use :xlink:href="symbolId" :fill="color" />
  </svg>
</template>

<script setup lang="ts">
const props = defineProps({<!-- -->
  prefix: {<!-- -->
    type: String,
    default: 'icon'
  },
  iconClass: {<!-- -->
    type: String,
    required: false,
    default: ''
  },
  color: {<!-- -->
    type: String,
    default: ''
  },
  size: {<!-- -->
    type: String,
    default: '1em'
  }
})

const symbolId = computed(() => `#${<!-- -->props.prefix}-${<!-- -->props.iconClass}`)
</script>

<style scoped>
.svg-icon {<!-- -->
  display: inline-block;
  width: 1em;
  height: 1em;
  overflow: hidden;
  vertical-align: -0.15em; /* Since the icon size is set to be consistent with the font size, and the lower edge of tags such as span will be aligned with the baseline of the font, a downward offset ratio needs to be set to correct the visual The misalignment effect*/
  outline: none;
  fill: currentcolor; /* Define the color of the element. currentColor is a variable. The value of this variable represents the color value of the current element. If the color value is not set for the current element, it is inherited from the parent element */
}
</style>
<template>
     <h1>img SVG local image:</h1>
    <svg-icon icon-class="homepage" />
    <svg-icon icon-class="user" color="red" />
</template>

<script setup lang="ts">
import SvgIcon from '@/components/SvgIcon/index.vue'
</script>

Renderings

4. Local PNG icon

There are still some differences between using local icons in vue3 and vue2

require used by vue2, such as:

Using require in vue3 and vite will report an error (require is not definedrequire is not defined), because require is webpack The method provided is not applicable in vite. In vite, since ES modules is used to load modules, require cannot be used, but import is used.

The following is how to use local PNG icons in vue3 (both debugging and online icons are displayed)

<template>
    <h1>img local PNG image:</h1>
    <img src="../../../assets/images/static/icon.png" />
    <img :src="imgPath2" />
    <img :src="imgPath3" />
    <img :src="imgPath4" />
    <img :src="imgPath5" />

    <h2>img dynamic import of local images:</h2>
    <img :src="getImgPath2('icon2.png')" />
    <img :src="getImgPath3('icon3.png')" />
</template>

<script setup lang="ts">
import imgPath2 from '@/assets/images/static/icon2.png'
const imgPath3 = getImgPath('icon3.png')
const imgPath4 = new URL(`../../../assets/images/static/icon4.png`, import.meta.url).href
const imgPath5 = new URL(`@/assets/images/static/icon5.png`, import.meta.url).href

const getImgPath2 = (name: string): any => {<!-- -->
  return new URL(`/src/assets/images/static/${<!-- -->name}`, import.meta.url).href
}

const getImgPath3 = (name: string): any => {<!-- -->
  return new URL(`../../../assets/images/static/${<!-- -->name}`, import.meta.url).href
}

</script>

!!!!Note:

 TODO: Loading failed when written as below, and @/assets/xxx cannot be used either.
  return new URL('/src/assets/images/static/' + name, import.meta.url).href

Renderings