自定义主题

Element Plus 默认提供一套主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。 但是如果需要大规模替换样式,例如: 将主题颜色从蓝色改为橙色或绿色,也许一个个将其覆盖起来不是一个好主意。

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

更换主题色

以下是自定义主题的一些例子。

通过 SCSS 变量

theme-chalk 使用SCSS编写而成。 你可以在 packages/theme-chalk/src/common/var.scss 主题 - 图3 文件中查找SCSS变量。

WARNING

我们使用 sass 模块( sass:map 主题 - 图4 …)和 @use 来重构所有的 SCSS 变量。 通过对所有 SCSS 变量使用 @use,解决了由 @import 造成的重复输出问题。

介绍Sass 模块 | CSS-TRICKS 主题 - 图5

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

$notification 是所有 notification 组件的变量的映射。

今后,我们将为每个组件自定义的变量编写文档。 你也可以直接查看源代码 var.scss 主题 - 图6

  1. $colors: () !default;
  2. $colors: map.deep-merge(
  3. (
  4. 'white': #ffffff,
  5. 'black': #000000,
  6. 'primary': (
  7. 'base': #409eff,
  8. ),
  9. 'success': (
  10. 'base': #67c23a,
  11. ),
  12. 'warning': (
  13. 'base': #e6a23c,
  14. ),
  15. 'danger': (
  16. 'base': #f56c6c,
  17. ),
  18. 'error': (
  19. 'base': #f56c6c,
  20. ),
  21. 'info': (
  22. 'base': #909399,
  23. ),
  24. ),
  25. $colors
  26. );

如何覆盖它?

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

WARNING

您应该使用 @use 'xxx.scss' as *; 代替 @import 'xxx.scss';

因为 sass 团队说他们最终会删除 @import 语法。

Sass: @use 主题 - 图7 vs Sass: @import 主题 - 图8

  1. // styles/element/index.scss
  2. /* 只需要重写你需要的即可 */
  3. @forward 'element-plus/theme-chalk/src/common/var.scss' with (
  4. $colors: (
  5. 'primary': (
  6. 'base': green,
  7. ),
  8. ),
  9. );
  10. // 如果只是按需导入,则可以忽略以下内容。
  11. // 如果你想导入所有样式:
  12. // @use "element-plus/theme-chalk/src/index.scss" as *;

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

TIP

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

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

TIP

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

  1. import { createApp } from 'vue'
  2. import './styles/element/index.scss'
  3. import ElementPlus from 'element-plus'
  4. import App from './App.vue'
  5. const app = createApp(App)
  6. app.use(ElementPlus)

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

使用 scss.additionalData 来编译所有应用 scss 变量的组件。

  1. import path from 'path'
  2. import { defineConfig } from 'vite'
  3. import vue from '@vitejs/plugin-vue'
  4. // 你也可以使用 unplugin-vue-components
  5. // import Components from 'unplugin-vue-components/vite'
  6. // import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
  7. // 或者使用 unplugin-element-plus
  8. import ElementPlus from 'unplugin-element-plus/vite'
  9. // vite.config.ts
  10. export default defineConfig({
  11. resolve: {
  12. alias: {
  13. '~/': `${path.resolve(__dirname, 'src')}/`,
  14. },
  15. },
  16. css: {
  17. preprocessorOptions: {
  18. scss: {
  19. additionalData: `@use "~/styles/element/index.scss" as *;`,
  20. },
  21. },
  22. },
  23. plugins: [
  24. vue(),
  25. // use unplugin-vue-components
  26. // Components({
  27. // resolvers: [
  28. // ElementPlusResolver({
  29. // importStyle: "sass",
  30. // // directives: true,
  31. // // version: "2.1.5",
  32. // }),
  33. // ],
  34. // }),
  35. // 或者使用 unplugin-element-plus
  36. ElementPlus({
  37. useSource: true,
  38. }),
  39. ],
  40. })

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

  1. // webpack.config.ts
  2. // 使用 unplugin-element-plus
  3. import ElementPlus from 'unplugin-element-plus/webpack'
  4. export default defineConfig({
  5. css: {
  6. loaderOptions: {
  7. scss: {
  8. additionalData: `@use "~/styles/element/index.scss" as *;`,
  9. },
  10. },
  11. },
  12. plugins: [
  13. ElementPlus({
  14. useSource: true,
  15. }),
  16. ],
  17. })

通过 CSS 变量设置

CSS 变量是一个非常有用的功能,几乎所有浏览器都支持。 (IE:啊这?)

使用CSS自定义属性(变量) | MDN 主题 - 图9 了解更多信息

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

TIP

它兼容 SCSS 变量系统。 我们使用 SCSS 的函数自动生成需要用到的 css 变量。

这意味着你可以动态地改变组件内的个别变量,以便更好地自定义组件样式,而不需要修改 SCSS 文件重新编译一次。

之后,每个组件的 css 变量名称和作用将被写入到对应的组件文档中。

就像这样:

  1. :root {
  2. --el-color-primary: green;
  3. }

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

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

出于性能原因,更加推荐你在类名下添加自定义 css 变量,而不是在全局的 :root 下。

  1. .custom-class {
  2. --el-tag-bg-color: red;
  3. }

如果您想要通过 js 控制 css 变量,可以这样做:

  1. // document.documentElement 是全局变量时
  2. const el = document.documentElement
  3. // const el = document.getElementById('xxx')
  4. // 获取 css 变量
  5. getComputedStyle(el).getPropertyValue(`--el-color-primary`)
  6. // 设置 css 变量
  7. el.style.setProperty('--el-color-primary', 'red')

如果你想要更优雅的方式,请看这里。 useCssVar | VueUse 主题 - 图10