Vue.js: UI Component Libraries

Last updated: 2026-10-20

A UI component library lets you avoid reinventing the wheel — common components such as Button / Table / Form / Modal take just a few lines of code. The Vue 3 ecosystem has 5+ mainstream UI libraries (Element Plus / Naive UI / Vuetify / PrimeVue / Ant Design Vue); picking the right one can save 50% of your development time.

Choosing a UI library comes down to 5 dimensions: component coverage / TypeScript support / theme customization / bundle size / community activity. This lesson helps you make the right call.

1. What You'll Learn


2. The Nightmare of Writing the Same "Table" Component 5 Times

(1) Pain point: every table written from scratch

Alice's admin has 5 different table views, each written from scratch:

5 tables × 200 lines = 1,000 lines of duplicated code. Every style change means editing 5 places.

(2) The UI library solution: one el-table, reused 5 times

VUE
<!-- ✅ The correct version: use Element Plus el-table -->
<template>
  <el-table :data="orders" stripe>
    <el-table-column prop="id" label="ID" width="80" />
    <el-table-column prop="user" label="User" />
    <el-table-column prop="total" label="Total" :formatter="formatTotal" />
  </el-table>
</template>

<script setup>
import { ElTable, ElTableColumn } from 'element-plus'

const orders = ref([...])
function formatTotal(row) { return `$${row.total}` }
</script>

One el-table, reused in 5 places. Every table now shares the same styling and the same interactions.

(3) The payoff

After adopting Element Plus:


3. Comparing the 5 Major Vue 3 UI Libraries

(1) Quick reference for the 5 libraries

Library Style Components Bundle size TypeScript Best for
Element Plus Desktop 80+ ~250KB ✅ Most popular in China, admin backends
Naive UI Desktop 80+ ~150KB ✅ Modern style, Vue 3 first
Vuetify Material 80+ ~300KB ✅ Material Design apps
PrimeVue Multi-style 90+ ~200KB ✅ Many themes, complete components
Ant Design Vue Ant Design 70+ ~180KB ✅ Ant style, enterprise-grade

(2) Detailed comparison across the 5 dimensions

Dimension Element Plus Naive UI Vuetify PrimeVue Ant Design Vue
GitHub ⭐ 24k+ 16k+ 40k+ 11k+ 20k+
Vue 3 first-class ✅ ✅ ✅ ✅ ✅
TypeScript ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐
Theme customization CSS variables CSS variables SCSS SCSS + theme less + theme
Bundle size Medium Small Large Medium Medium
Chinese docs ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐
Community activity ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐
Learning curve Gentle Gentle Medium Medium Medium

(3) 5 selection recommendations

Scenario Recommendation
Chinese admin backends (e-commerce/CRM/ERP) Element Plus ⭐⭐⭐⭐⭐
Modern-style SaaS Naive UI ⭐⭐⭐⭐
Material Design apps Vuetify ⭐⭐⭐⭐
Multiple themes (dark/light/high contrast) PrimeVue ⭐⭐⭐⭐
The Ant Design ecosystem Ant Design Vue ⭐⭐⭐⭐

4. Element Plus in Practice

(1) Installation

BASH
npm install element-plus @element-plus/icons-vue

(2) Global registration (simple)

BASH
npm install -D unplugin-vue-components unplugin-auto-import
TS
// vite.config.ts
import AutoImport from 'unplugin-auto-import'
import Components from 'unplugin-vue-components'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  plugins: [
    AutoImport({
      resolvers: [ElementPlusResolver()],
      dts: 'src/auto-imports.d.ts'
    }),
    Components({
      resolvers: [ElementPlusResolver()],
      dts: 'src/components.d.ts'
    })
  ]
})

(4) The 5 core components

▶ Example: Hand-Building a Library-Style Button + Card with Plain CSS (browser-runnable)

💡 This is a browser-runnable equivalent demo: no Element Plus, just props + slots + one set of CSS classes to reproduce its button and card, which shows that a component library is really "one API + one visual language".

▶ Expand runnable example (78 lines)
▶ Try it Yourself

Output:

TEXT
First render: an outlined "Default" button, a large blue "Primary" button and a red "Delete" button; below them a card titled "Order #1024" with the total and a small blue button, and the hint "Waiting for input".
Click "Delete": the button greys out and shows "⏳ Delete" (disabled while loading) and the hint becomes "Deleting…"; about 800ms later it is clickable again and the hint reads "Deleted (request simulated)".
The same type / size / loading / disabled props plus slots produce 4 different looks — exactly the essence of libraries like Element Plus: components with one visual language and one API.

5. Theme Customization

SCSS
// src/styles/element-plus.scss
:root {
  --el-color-primary: #42b883;       // change the primary color to Vue green
  --el-color-success: #67c23a;
  --el-color-warning: #e6a23c;
  --el-color-danger: #f56c6c;
  --el-color-info: #909399;
  
  --el-border-radius-base: 8px;      // larger corner radius
  --el-font-size-base: 14px;
}
JS
// main.js
import './styles/element-plus.scss'
import 'element-plus/dist/index.css'

(2) SCSS variables (deep customization)

SCSS
// src/styles/element-plus-vars.scss
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': ('base': #42b883),
    'success': ('base': #67c23a),
    'warning': ('base': #e6a23c),
    'danger':  ('base': #f56c6c),
    'info':    ('base': #909399)
  )
);
JS
// main.js
import './styles/element-plus-vars.scss'
import 'element-plus/dist/index.css'

(3) Dark mode

SCSS
// Dark theme
:root {
  --el-color-primary: #42b883;
  --el-bg-color: #1a1a1a;
  --el-text-color-primary: #ffffff;
}

html.dark {
  --el-bg-color: #1a1a1a;
  --el-text-color-primary: #ffffff;
}

▶ Example: The 5 Theme Customizations

SCSS
/* 1. CSS variables (recommended) */
:root { --el-color-primary: #42b883; }

/* 2. SCSS variables (deep customization) */
@forward 'var.scss' with ($colors: ...);

/* 3. Dark mode */
:root.dark { --el-bg-color: #1a1a1a; }

/* 4. Custom theme */
@import 'element-plus/theme-chalk/dark/css-vars.css';

/* 5. Runtime switching */
document.documentElement.classList.toggle('dark')
▶ Try it Yourself

Output:

TEXT
Compiled as-is, this stylesheet repaints every Element Plus component — the primary color turns Vue green, and toggling the dark class on <html> flips the background to #1a1a1a:
TEXT
Before: primary #409eff, background #ffffff
After:  primary #42b883, background #1a1a1a (when <html class="dark">)

6. Wrapping Components

(1) A business component example

VUE
<!-- Usage: one table in 3 lines -->
<BusinessTable :data="orders" :columns="orderColumns" :total="100" />

(2) The 5 benefits of wrapping


7. Icon Library Integration

(1) Installation

BASH
npm install -D unplugin-icons @iconify-json/carbon

(2) Configuration

TS
// vite.config.ts
import Icons from 'unplugin-icons/vite'
import { FileSystemIconLoader } from 'unplugin-icons/dist/loader'

export default defineConfig({
  plugins: [
    Icons({
      compiler: 'vue3',
      autoInstall: true,  // install icon sets automatically
      collections: {
        carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default)
      }
    })
  ]
})

(3) Usage

(4) Comparing the 5 major icon libraries

Library Icons Loading Bundle size
Iconify 200,000+ On demand (recommended) 0
Element Icons 300+ All / on demand 100KB
Material Icons 2,000+ All / on demand 300KB
Font Awesome 7,000+ All 1MB+
Heroicons 300+ On demand 50KB

8. Putting It Together: Five Components for an Admin UI

(1) 📊 Comparing the 5 UI Libraries (⚠️ Requires Vite + npm install)

Library ⭐ Bundle size Style
Element Plus 24k Medium Desktop
Naive UI 16k Small Modern
Vuetify 40k Large Material
PrimeVue 11k Medium Multi-style
Ant Design Vue 20k Medium Ant Design

Output:

TEXT
The block renders as a four-column comparison table covering all five libraries:
TEXT
Library           ⭐     Bundle size  Style
----------------  ----  -----------  --------------
Element Plus      24k   Medium       Desktop
Naive UI          16k   Small        Modern
Vuetify           40k   Large        Material
PrimeVue          11k   Medium       Multi-style
Ant Design Vue    20k   Medium       Ant Design

▶ Example: The 5 Core Components (Element Plus)

VUE
<!-- Requires Vite + npm install element-plus -->
<el-button>Button</el-button>
<el-form>Form</el-form>
<el-table>Table</el-table>
<el-dialog>Dialog</el-dialog>
<el-message>Message</el-message>
▶ Try it Yourself

Output:

TEXT
With Element Plus installed, each tag renders as its styled Element Plus widget (a primary button, a form container, a striped table, a modal dialog, and a top toast):
TEXT
[ Button ]      ← <el-button>
< el-form >     ← form container, label width applied
┌──────────────┐
│ Table header │ ← <el-table>
└──────────────┘
┌ Dialog ──────┐ ← <el-dialog> (hidden until v-model="visible")
└──────────────┘
✓ Saved!        ← <el-message> (auto-dismiss toast)

(2) 📊 The 5 Icon Libraries

Library Icons
Iconify 200,000+
Element Icons 300+
Material 2,000+
Font Awesome 7,000+
Heroicons 300+

Output:

TEXT
The block renders as a two-column table ordered from the largest collection to the smallest:
TEXT
Library         Icons
--------------  ---------
Iconify         200,000+
Element Icons   300+
Material        2,000+
Font Awesome    7,000+
Heroicons       300+

(3) 📊 Quick Reference for 5 Common Mistakes

Error Symptom Solution
Importing everything bloats the bundle bundle 500KB Use unplugin-vue-components for on-demand imports
Theme color will not change SCSS was used Switch to CSS variables
Icons do not appear Font failed to load Use unplugin-icons SVG
TS type errors import has no types Install the @types package
i18n stops working Wrong locale Configure i18n

Output:

TEXT
The block renders as a five-row troubleshooting table covering bundle size, theming, icons, types and locales:
TEXT
Error                          Symptom            Solution
-----------------------------  -----------------  ------------------------------
Full import bloats the bundle  bundle 500KB       unplugin-vue-components
Theme color will not change    SCSS was used      Switch to CSS variables
Icons do not appear            Font load failed   Use unplugin-icons SVG
TS type errors                 import has no types Install the @types package
i18n stops working             Wrong locale       Configure i18n

❓ FAQ

Q Which of the 5 UI libraries should I pick?
A Chinese admin backends → Element Plus (most popular). Modern SaaS → Naive UI (small and elegant). Material apps → Vuetify. Ant Design ecosystem → Ant Design Vue.
Q Full import or on-demand import?
A Full import is simple but the bundle is large (500KB). On-demand (unplugin-vue-components) is recommended — it saves 50% of the size.
Q How do I change the Element Plus theme color?
A Override the CSS variable --el-color-primary. Customizing SCSS variables requires compiling the theme with unplugin-element-plus.
Q Does Element Plus fully support TypeScript?
A Yes. Element Plus 2.x is a complete TypeScript rewrite with full type inference.
Q Can I mix UI libraries (e.g. Element Plus + Naive UI)?
A Technically yes, but style conflicts are painful to resolve. Not recommended — pick one main library plus one lightweight one (e.g. Element Plus + Headless UI).
Q unplugin-vue-components vs global registration?
A unplugin imports on demand automatically and the bundle is 50% smaller. Global registration is simple but the bundle is larger. On-demand is recommended.
Q How do I choose an icon library?
A Iconify (200,000+ across many sets) plus unplugin-icons for on-demand imports. Zero runtime overhead.

📖 Summary


📝 Exercises

  1. Basic (Difficulty: ⭐) Integrate Element Plus into a Vue 3 project:

    • Install + on-demand imports
    • 5 core components (Button / Form / Table / Dialog / Message)
    • Change the theme color to the project's primary color
  2. Intermediate (Difficulty: ⭐⭐) Implement a complete Element Plus integration:

    • Use all 5 major components (Button / Form / Table / Dialog / Message)
    • Dark mode toggle
    • Iconify icons (10 different icons)
    • Wrap a BusinessTable component
  3. Challenge (Difficulty: ⭐⭐⭐) Build a complete "enterprise-grade UI library integration":

    1. Element Plus + Naive UI mixed (primary + secondary)
    2. 5 theme colors (primary / secondary / success / warning / danger)
    3. Dark mode + automatic system preference
    4. 10+ wrapped business components
    5. Iconify 200,000+ icons
    6. Strong TypeScript typing
    7. Performance optimization (on-demand + tree shaking + CDN)
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏