Skip to content

Button Component

Overview

The Button component is one of the most fundamental interactive elements in Element Plus. It provides various styles, sizes, and states to meet different design requirements.

Basic Usage

Default Buttons

vue
<template>
  <div class="button-demo">
    <el-button>Default</el-button>
    <el-button type="primary">Primary</el-button>
    <el-button type="success">Success</el-button>
    <el-button type="info">Info</el-button>
    <el-button type="warning">Warning</el-button>
    <el-button type="danger">Danger</el-button>
  </div>
</template>

<style>
.button-demo .el-button {
  margin-right: 10px;
  margin-bottom: 10px;
}
</style>

Plain Buttons

vue
<template>
  <div class="button-demo">
    <el-button plain>Plain</el-button>
    <el-button type="primary" plain>Primary</el-button>
    <el-button type="success" plain>Success</el-button>
    <el-button type="info" plain>Info</el-button>
    <el-button type="warning" plain>Warning</el-button>
    <el-button type="danger" plain>Danger</el-button>
  </div>
</template>

Button Sizes

vue
<template>
  <div class="button-demo">
    <el-button size="large">Large</el-button>
    <el-button>Default</el-button>
    <el-button size="small">Small</el-button>
  </div>
</template>

Button States

Disabled State

vue
<template>
  <div class="button-demo">
    <el-button disabled>Disabled</el-button>
    <el-button type="primary" disabled>Primary Disabled</el-button>
    <el-button type="success" disabled>Success Disabled</el-button>
  </div>
</template>

Loading State

vue
<template>
  <div class="button-demo">
    <el-button loading>Loading</el-button>
    <el-button type="primary" loading>Primary Loading</el-button>
    <el-button 
      type="success" 
      :loading="isLoading"
      @click="handleClick"
    >
      Click to Load
    </el-button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const isLoading = ref(false)

const handleClick = () => {
  isLoading.value = true
  setTimeout(() => {
    isLoading.value = false
  }, 2000)
}
</script>

Icon Buttons

With Icons

vue
<template>
  <div class="button-demo">
    <!-- Using Element Plus icons -->
    <el-button type="primary" :icon="Edit">Edit</el-button>
    <el-button type="success" :icon="Check">Confirm</el-button>
    <el-button type="danger" :icon="Delete">Delete</el-button>
    
    <!-- Icon only buttons -->
    <el-button type="primary" :icon="Search" circle />
    <el-button type="success" :icon="Plus" circle />
    <el-button type="danger" :icon="Close" circle />
  </div>
</template>

<script setup>
import { Edit, Check, Delete, Search, Plus, Close } from '@element-plus/icons-vue'
</script>

Custom Icons

vue
<template>
  <div class="button-demo">
    <el-button>
      <template #icon>
        <svg viewBox="0 0 1024 1024" width="1em" height="1em">
          <path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z" fill="currentColor"/>
        </svg>
      </template>
      Custom Icon
    </el-button>
  </div>
</template>

Button Groups

vue
<template>
  <div class="button-demo">
    <el-button-group>
      <el-button type="primary" :icon="ArrowLeft">Previous</el-button>
      <el-button type="primary" :icon="ArrowRight">Next</el-button>
    </el-button-group>
    
    <el-button-group>
      <el-button :icon="Edit" />
      <el-button :icon="Share" />
      <el-button :icon="Delete" />
    </el-button-group>
  </div>
</template>

<script setup>
import { ArrowLeft, ArrowRight, Edit, Share, Delete } from '@element-plus/icons-vue'
</script>

Advanced Usage

Text Buttons

vue
<template>
  <div class="button-demo">
    <el-button text>Text Button</el-button>
    <el-button text type="primary">Primary Text</el-button>
    <el-button text type="success">Success Text</el-button>
    <el-button text type="danger">Danger Text</el-button>
    <el-button text disabled>Disabled Text</el-button>
  </div>
</template>
vue
<template>
  <div class="button-demo">
    <el-button link type="primary">Primary Link</el-button>
    <el-button link type="success">Success Link</el-button>
    <el-button link type="danger">Danger Link</el-button>
    <el-button link disabled>Disabled Link</el-button>
  </div>
</template>

Round and Circle Buttons

vue
<template>
  <div class="button-demo">
    <!-- Round buttons -->
    <el-button round>Round</el-button>
    <el-button type="primary" round>Primary Round</el-button>
    <el-button type="success" round>Success Round</el-button>
    
    <!-- Circle buttons -->
    <el-button :icon="Search" circle />
    <el-button type="primary" :icon="Edit" circle />
    <el-button type="success" :icon="Check" circle />
  </div>
</template>

<script setup>
import { Search, Edit, Check } from '@element-plus/icons-vue'
</script>

Event Handling

vue
<template>
  <div class="button-demo">
    <el-button @click="handleClick">Click Me</el-button>
    <el-button @click="handleAsyncAction" :loading="loading">
      Async Action
    </el-button>
    <el-button @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
      Hover Me
    </el-button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'

const loading = ref(false)

const handleClick = () => {
  ElMessage.success('Button clicked!')
}

const handleAsyncAction = async () => {
  loading.value = true
  try {
    // Simulate async operation
    await new Promise(resolve => setTimeout(resolve, 2000))
    ElMessage.success('Action completed!')
  } catch (error) {
    ElMessage.error('Action failed!')
  } finally {
    loading.value = false
  }
}

const handleMouseEnter = () => {
  console.log('Mouse entered')
}

const handleMouseLeave = () => {
  console.log('Mouse left')
}
</script>

Customization

Custom Styles

vue
<template>
  <div class="button-demo">
    <el-button class="custom-button">Custom Styled</el-button>
    <el-button class="gradient-button">Gradient Button</el-button>
  </div>
</template>

<style>
.custom-button {
  --el-button-bg-color: #ff6b6b;
  --el-button-border-color: #ff6b6b;
  --el-button-hover-bg-color: #ff5252;
  --el-button-hover-border-color: #ff5252;
}

.gradient-button {
  background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
  border: none;
  color: white;
}

.gradient-button:hover {
  background: linear-gradient(45deg, #5a6fd8 0%, #6a4190 100%);
}
</style>

Theme Variables

scss
// Custom button theme
:root {
  --el-button-font-size: 14px;
  --el-button-border-radius: 6px;
  --el-button-padding-horizontal: 20px;
  --el-button-padding-vertical: 12px;
}

// Size-specific customization
.el-button--large {
  --el-button-padding-horizontal: 24px;
  --el-button-padding-vertical: 16px;
  --el-button-font-size: 16px;
}

.el-button--small {
  --el-button-padding-horizontal: 16px;
  --el-button-padding-vertical: 8px;
  --el-button-font-size: 12px;
}

API Reference

Button Props

PropTypeDefaultDescription
size'large' | 'default' | 'small''default'Button size
type'primary' | 'success' | 'warning' | 'danger' | 'info'''Button type
plainbooleanfalseWhether button is plain
textbooleanfalseWhether button is text button
linkbooleanfalseWhether button is link button
roundbooleanfalseWhether button is round
circlebooleanfalseWhether button is circle
loadingbooleanfalseWhether button is loading
disabledbooleanfalseWhether button is disabled
iconComponentundefinedIcon component
autofocusbooleanfalseWhether button should autofocus
native-type'button' | 'submit' | 'reset''button'Native button type

Button Events

EventParametersDescription
click(event: MouseEvent)Triggered when button is clicked
focus(event: FocusEvent)Triggered when button gains focus
blur(event: FocusEvent)Triggered when button loses focus

Button Slots

SlotDescription
defaultButton content
iconCustom icon
loadingCustom loading icon

Best Practices

1. Choose Appropriate Types

vue
<!-- ✅ Good: Use semantic button types -->
<el-button type="primary">Save</el-button>
<el-button type="danger">Delete</el-button>
<el-button type="success">Confirm</el-button>

<!-- ❌ Bad: Misusing button types -->
<el-button type="danger">Save</el-button>
<el-button type="success">Cancel</el-button>

2. Provide Clear Labels

vue
<!-- ✅ Good: Clear, action-oriented labels -->
<el-button type="primary">Save Changes</el-button>
<el-button>Cancel</el-button>

<!-- ❌ Bad: Vague labels -->
<el-button type="primary">OK</el-button>
<el-button>No</el-button>

3. Use Loading States

vue
<!-- ✅ Good: Show loading state for async actions -->
<el-button 
  type="primary" 
  :loading="isSubmitting"
  @click="handleSubmit"
>
  {{ isSubmitting ? 'Saving...' : 'Save' }}
</el-button>

4. Accessibility

vue
<!-- ✅ Good: Proper accessibility attributes -->
<el-button 
  :aria-label="buttonLabel"
  :aria-disabled="disabled"
  role="button"
>
  {{ text }}
</el-button>

Common Patterns

Form Actions

vue
<template>
  <div class="form-actions">
    <el-button type="primary" @click="handleSubmit">Submit</el-button>
    <el-button @click="handleReset">Reset</el-button>
    <el-button text @click="handleCancel">Cancel</el-button>
  </div>
</template>

<style>
.form-actions {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
  margin-top: 24px;
}
</style>

Toolbar Actions

vue
<template>
  <div class="toolbar">
    <el-button-group>
      <el-button :icon="Plus" @click="handleAdd">Add</el-button>
      <el-button :icon="Edit" @click="handleEdit" :disabled="!selected">
        Edit
      </el-button>
      <el-button :icon="Delete" @click="handleDelete" :disabled="!selected">
        Delete
      </el-button>
    </el-button-group>
  </div>
</template>

Next Steps


The Button component is the foundation of user interactions. Master its usage to build intuitive interfaces. 🎯

Element Plus Study Guide