Building a Custom Icon Component Based on Element Plus el-icon

The icon system changed significantly between Element UI and Element Plus, with the latter adopting SVG icons. If you are accustomed to the Element UI aproach but prefer working with Vue 3, you can wrap Element Plus icons into a custom component that replicates the simpler interface of the older library.

Design Goals

The custom <e-icon> component should provide:

  • A type property to select a specific SVG icon.
  • A size property that accepts both numbers and strings. Element Plus only accepts number, which forces v-bind:size="20" or the shorthand :size="20". Supporting strings like size="20" avoids the occasional mistake of forgetting the v-bind.
  • The type property should be case‑insensitive for the first character. Element Plus uses PascalCase for icon names, but short words are easy to mistype.
  • The color property works exactly as in Element Plus.

Example usage:

<e-icon type="Aim" :size="36" color="rgba(53, 131, 208, 0.5)" />

Note that the tag is not <el-icon>; the wrapper is named <e-icon> to emphasice its simplified nature.

Trade‑offs

The bundle size may increase slgihtly because all SVG icons must be imported.

Implementation

The development relies on:

  • Component communication via props
  • Dynamic components
  • Full import of all Element Plus SVG icons

The component code is straightforward. Follow these steps:

  1. Import all SVG icons from @element-plus/icons-vue.
  2. Import the icon component CSS.
  3. Accept size, color, and type props.
  4. Convert the size prop to a number (Element Plus expects a number).
  5. Ensure the first character of the type string is uppercase.
  6. Dynamically resolve the icon component using bracket notation.
<template>
  <ElIcon :size="normalizedSize" :color="color">
    <component :is="resolvedIcon" />
  </ElIcon>
</template>

<script>
export default {
  name: 'EIcon'
}
</script>

<script setup>
import { computed } from 'vue'
import { ElIcon } from 'element-plus'
import * as Icons from '@element-plus/icons-vue'
import 'element-plus/es/components/icon/style/css'

const props = defineProps({
  size: {
    type: [Number, String],
    default: 14,
    validator(value) {
      return !isNaN(value)
    }
  },
  color: {
    type: String,
    default: 'inherit'
  },
  type: {
    type: String,
    default: ''
  }
})

const normalizedSize = computed(() => {
  if (isNaN(props.size)) {
    return 20
  }
  return Number(props.size)
})

const resolvedIcon = computed(() => {
  const rawType = props.type
  if (rawType === '') return null
  const corrected = rawType.charAt(0).toUpperCase() + rawType.slice(1)
  return Icons[corrected] || null
})
</script>

Notice the separate <script> block that declares the component name – this is a common pattern even when using <script setup>.

Usage

Import and use the component in a Vue template:

<template>
  <div>
    <EIcon type="Aim" :size="36" color="rgba(53, 131, 208, 0.5)" />
  </div>
</template>

<script setup>
import EIcon from '@/components/EIcon/index.vue'
</script>

Alternatively, register EIcon globally in main.js with app.component('EIcon', EIcon).

Tags: vue3 Element Plus Icon Component SVG Icons Component Wrapper

Posted on Wed, 17 Jun 2026 16:48:23 +0000 by idris