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