自定义主题

Element Plus 的样式使用了 BEM 命名规范,所以,你可以很简单地覆盖样式。 但是,如果你需要大范围地修改样式,例如,把主题色从蓝色改成橙色或者绿色,也许一个一个地覆盖不是一个好主意。

我们提供了四种方式来修改样式变量。

修改主题色

这里有一些自定义主题的示例。

通过 SCSS 变量

theme-chalk 是用 SCSS 编写的。 您可以在 packages/theme-chalk/src/common/var.scss 中找到 SCSS 变量。

警告

我们使用了 sass modules (sass:map ...) 和 @use 来重构所有的 SCSS 变量。通过对所有 SCSS 变量使用 @use,解决了 @import 导致的重复输出问题。

介绍 Sass 模块 | CSS-TRICKS

例如,我们使用 $colors 作为映射来保留不同类型的颜色。

$notification 是一个 map,其中包含 notification 组件的所有变量。

将来,我们会为每个组件编写可定制的变量的文档。 您也可以直接查看源码 var.scss

scss
$colors: () !default;
$colors: map.deep-merge(
  (
    'white': #ffffff,
    'black': #000000,
    'primary': (
      'base': #409eff,
    ),
    'success': (
      'base': #67c23a,
    ),
    'warning': (
      'base': #e6a23c,
    ),
    'danger': (
      'base': #f56c6c,
    ),
    'error': (
      'base': #f56c6c,
    ),
    'info': (
      'base': #909399,
    ),
  ),
  $colors
);

如何覆盖它?

如果你的项目也使用了 SCSS,你可以直接修改 Element Plus 的样式变量。 创建一个新的样式文件,例如 styles/element/index.scss

警告

您应该使用 @use 'xxx.scss' as *; 而不是 @import 'xxx.scss';

因为 sass 团队表示他们最终将删除 @import

Sass: @use vs Sass: @import

styles/element/index.scss
scss
/* just override what you need */
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': (
      'base': green,
    ),
  )
);

// If you just import on demand, you can ignore the following content.
// if you want to import all styles:
// @use "element-plus/theme-chalk/src/index.scss" as *;

然后在你的项目入口文件中,导入这个样式文件来替换 Element 的内置 CSS

提示

在 element-plus 的 scss 之前导入 element/index.scss 以避免 sass 混合变量的问题,因为我们需要通过您的自定义变量生成 light-x。

创建一个 element/index.scss 来组合你的变量和 element-plus 的变量。 (如果你在 ts 中导入它们,它们将不会被合并。)

提示

另外,您应该将您的 scss 与 element 变量 scss 区分开来。 如果它们混合在一起,element-plus 的每次热更新都需要编译大量的 scss 文件,导致速度变慢。

main.ts
ts
import { createApp } from 'vue'
import './styles/element/index.scss'
import ElementPlus from 'element-plus'
import App from './App.vue'

const app = createApp(App)
app.use(ElementPlus)

如果你正在使用 vite,并且你希望在按需导入时自定义主题。

使用 scss.additionalData 将变量与每个组件的 scss 一起编译。

vite.config.ts
ts
import path from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// You can also use unplugin-vue-components
// import Components from 'unplugin-vue-components/vite'
// import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// or use unplugin-element-plus
import ElementPlus from 'unplugin-element-plus/vite'

export default defineConfig({
  resolve: {
    alias: {
      '~/': `${path.resolve(__dirname, 'src')}/`,
    },
  },
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@use "~/styles/element/index.scss" as *;`,
      },
    },
  },
  plugins: [
    vue(),
    // use unplugin-vue-components
    // Components({
    //   resolvers: [
    //     ElementPlusResolver({
    //       importStyle: "sass",
    //       // directives: true,
    //       // version: "2.1.5",
    //     }),
    //   ],
    // }),
    // or use unplugin-element-plus
    ElementPlus({
      useSource: true,
    }),
  ],
})

如果你正在使用 webpack,并且你希望在按需导入时自定义主题。

webpack.config.js
js
// use unplugin-element-plus

import ElementPlus from 'unplugin-element-plus/webpack'

export default defineConfig({
  css: {
    loaderOptions: {
      scss: {
        additionalData: `@use "~/styles/element/index.scss" as *;`,
      },
    },
  },
  plugins: [
    ElementPlus({
      useSource: true,
    }),
  ],
})

通过 CSS 变量

CSS 变量是一个非常有用的特性,几乎所有浏览器都支持。(IE:等等?)

使用 CSS 自定义属性(变量)| MDN 了解更多

我们用 CSS 变量重构了几乎所有组件的样式系统。

提示

它与 SCSS 变量系统兼容。我们使用 SCSS 的函数自动生成 CSS 变量以供使用。

这意味着您可以动态地更改组件内的单个变量以更好地对其进行自定义,而无需修改 SCSS 并重新编译它。

未来,每个组件的 CSS 变量名称和作用文档将写入每个组件中。

像这样

css
:root {
  --el-color-primary: green;
}

如果你只是想自定义某个特定的组件,只需要为某些组件单独添加内联样式即可。

html
<el-tag style="--el-tag-bg-color: red">Tag</el-tag>

出于性能原因,更推荐在一个 class 下自定义 CSS 变量,而不是全局的 :root

css
.custom-class {
  --el-tag-bg-color: red;
}

如果你想通过脚本控制 CSS 变量,试试这个

ts
// document.documentElement is global
const el = document.documentElement
// const el = document.getElementById('xxx')

// get css var
getComputedStyle(el).getPropertyValue(`--el-color-primary`)

// set css var
el.style['--el-color-primary'] = 'red'

如果你想要更优雅的方式,请查看这个。 useCssVar | VueUse