Element Plus 主题样式自定义指南

概述

elementplus自定义了一套主题颜色,默认以蓝色为主。但有时候,我们的业务需要支持其它配色方案,这时候就需要有一个简单的全局文件可以替换ElementPlus默认的配色。

实现原理

Elementplus中,主要定义了5种颜色,每一种颜色有5中浅色变体,1种深色变体:

  • light-3: 基础颜色与白色混合,透明度约25%
  • light-5: 基础颜色与白色混合,透明度约50%
  • light-7: 基础颜色与白色混合,透明度约75%
  • light-8: 基础颜色与白色混合,透明度约85%
  • light-9: 基础颜色与白色混合,透明度约95%
  • dark-2: 基础颜色变暗约20%生成

Element Plus使用了Sass的颜色混合函数来生成各种变体。所以,我们需要仿照其格式编写一个属于我们自己的sass颜色配置文件,以完全覆盖前者(主要是覆盖各种控件的配色,如果需要修改字体配色可以把本代码拿去问AI,让AI给你加上)。

文件结构

在这里插入图片描述

实施步骤

1. 创建主题文件

在 src/assets/styles/element-plus/theme.scss 中创建主题文件:

// Element Plus 自定义主题 - 使用Sass自动生成颜色变体
@use 'sass:color';
@use 'sass:map';
@use 'sass:meta';

// 基础颜色配置
$colors: (
  'primary': #ff8343,
  'success': #59c9c5,  
  'warning': #4148a6,  
  'danger': #e74c3c,   
  'error': #ff3860,    
  'info': #3498db      
);

// 生成颜色变体的函数
@function generate-color-variants($base-color) {
  $variants: ();
  
  // 基础颜色
  $variants: map.merge($variants, ('base': $base-color));
  
  // Light variants (3, 5, 7, 8, 9)
  $variants: map.merge($variants, ('light-3': color.mix(#fff, $base-color, 5%)));
  $variants: map.merge($variants, ('light-5': color.mix(#fff, $base-color, 15%)));
  $variants: map.merge($variants, ('light-7': color.mix(#fff, $base-color, 30%)));
  $variants: map.merge($variants, ('light-8': color.mix(#fff, $base-color, 50%)));
  $variants: map.merge($variants, ('light-9': color.mix(#fff, $base-color, 70%)));
  
  // Dark variants
  $variants: map.merge($variants, ('dark-2': color.mix(#000, $base-color, 20%)));
  
  @return $variants;
}

// 生成RGB值的函数
@function get-rgb-values($color) {
  @return #{color.channel($color, 'red')}, #{color.channel($color, 'green')}, #{color.channel($color, 'blue')};
}

// 生成所有颜色的变体
$color-variants: ();
@each $name, $color in $colors {
  $color-variants: map.merge($color-variants, ($name: generate-color-variants($color)));
}

// 输出CSS变量
:root {
  // 为每种颜色生成所有变体
  @each $color-name, $variants in $color-variants {
    @each $variant-name, $variant-color in $variants {
      --el-color-#{$color-name}#{if($variant-name != 'base', '-' + $variant-name, '')}: #{$variant-color};
    }
    
    // 生成RGB值
    --el-color-#{$color-name}-rgb: #{get-rgb-values(map.get($variants, 'base'))};
  }
  
  // 错误色使用危险色的值
  --el-color-error: var(--el-color-danger);
  --el-color-error-rgb: var(--el-color-danger-rgb);
  @each $variant in ('light-3', 'light-5', 'light-7', 'light-8', 'light-9', 'dark-2') {
    --el-color-error-#{$variant}: var(--el-color-danger-#{$variant});
  }
  
  // 文本颜色
  --el-text-color-primary: #303133;
  --el-text-color-regular: #606266;
  --el-text-color-secondary: #909399;
  --el-text-color-placeholder: #a8abb2;
  --el-text-color-disabled: #c0c4cc;
  
  // 边框颜色
  --el-border-color: #dcdfe6;
  --el-border-color-light: #e4e7ed;
  --el-border-color-lighter: #ebeef5;
  --el-border-color-extra-light: #f2f6fc;
  --el-border-color-dark: #d4d7de;
  --el-border-color-darker: #cdd0d6;
  
  // 填充颜色
  --el-fill-color: #f0f2f5;
  --el-fill-color-light: #f5f7fa;
  --el-fill-color-lighter: #fafafa;
  --el-fill-color-extra-light: #fafcff;
  --el-fill-color-dark: #ebedf0;
  --el-fill-color-darker: #e6e8eb;
  --el-fill-color-blank: #ffffff;
  
  // 背景颜色
  --el-bg-color: #ffffff;
  --el-bg-color-page: #f2f3f5;
  --el-bg-color-overlay: #ffffff;
  
  // 禁用状态
  --el-disabled-bg-color: var(--el-fill-color-light);
  --el-disabled-text-color: var(--el-text-color-placeholder);
  --el-disabled-border-color: var(--el-border-color-light);
  
  // 组件特定变量
  --el-button-hover-text-color: var(--el-color-primary);
  --el-button-hover-bg-color: var(--el-color-primary-light-9);
  --el-button-hover-border-color: var(--el-color-primary-light-7);
  --el-button-active-text-color: var(--el-button-hover-text-color);
  --el-button-active-border-color: var(--el-color-primary);
  --el-button-active-bg-color: var(--el-button-hover-bg-color);
  
  --el-menu-active-color: var(--el-color-primary);
  --el-menu-hover-bg-color: var(--el-color-primary-light-9);
  --el-menu-hover-text-color: var(--el-color-primary);
  
  --el-table-row-hover-bg-color: var(--el-fill-color-light);
  --el-table-current-row-bg-color: var(--el-color-primary-light-9);
  
  --el-message-bg-color: var(--el-color-info-light-9);
  --el-message-border-color: var(--el-border-color-lighter);
  
  // 表单组件
  --el-checkbox-checked-text-color: var(--el-color-primary);
  --el-checkbox-checked-input-border-color: var(--el-color-primary);
  --el-checkbox-checked-bg-color: var(--el-color-primary);
  --el-checkbox-checked-icon-color: var(--el-color-white);
  
  --el-radio-checked-text-color: var(--el-color-primary);
  --el-radio-checked-input-border-color: var(--el-color-primary);
  --el-radio-checked-icon-color: var(--el-color-primary);
  
  --el-select-option-selected-text-color: var(--el-color-primary);
  --el-select-input-focus-border-color: var(--el-color-primary);
  
  --el-switch-on-color: var(--el-color-primary);
  --el-link-hover-text-color: var(--el-color-primary);
}

// 基础颜色定义
:root {
  --el-color-white: #ffffff;
  --el-color-black: #000000;
}

2. 创建主样式文件(如果你有的话)

在 src/assets/styles/main.scss 中引入主题文件:

// 引入Element Plus默认样式
@import 'element-plus/dist/index.css';

// 引入自定义主题
@import './element-plus/theme.scss';

// 其他全局样式...

3. 编译scss文件

npx sass element-plus-theme.scss element-plus-theme.css

命令结构:npx sass [输入文件] [输出文件]
编译完之后会在同目录下看到一些css文件

4. 修改 Vue 入口文件

在 src/main.js 中引入主样式文件:

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'

// 引入全局样式
import '@/assets/styles/element-theme.css'	// 视你的具体路径决定

createApp(App).use(ElementPlus).mount('#app')

5. 安装必要的依赖

确保已安装 Element Plus 和 Sass:

npm install element-plus
npm install sass --save-dev

自定义配置说明

修改基础颜色

在 theme.scss 中修改 $colors 映射:

在这里插入图片描述

添加新的颜色变体

在 generate-color-variants 函数中添加新的变体:

// 添加新的变体
$variants: map.merge($variants, ('light-2': color.mix(#fff, $base-color, 10%)));
$variants: map.merge($variants, ('dark-1': color.mix(#000, $base-color, 10%)));

扩展组件样式

在 :root 选择器中添加新的组件变量:

:root {
  // 添加新的组件变量
  --el-your-component-bg-color: var(--el-color-primary-light-8);
  --el-your-component-text-color: var(--el-text-color-primary);
}

注意事项

  1. 确保自定义主题文件在 Element Plus 默认样式之后导入
  2. 编译前检查 Sass 版本兼容性(需要支持 @use 规则)
  3. 颜色对比度需满足可访问性要求
  4. 在生产环境中使用压缩后的 CSS 文件以提高性能

验证结果

编译项目后,打开浏览器开发者工具,检查 CSS 变量是否已正确覆盖👇
在这里插入图片描述
我的项目中效果如下:
在这里插入图片描述
在这里插入图片描述

更多推荐