Element Plus 如何按设计规范统一组件的边框、圆角与阴影?
2026/9/13 22:33:37 网站建设 项目流程

Element Plus 如何按设计规范统一组件的边框、圆角与阴影?

【免费下载链接】element-plus🎉 A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus

当多个开发者在同一个 Vue 3 项目里写样式时,按钮的圆角、卡片的边框和弹层的阴影很容易各写各的。Element Plus 的 Border 设计文档 把按钮、卡片、弹层等组件可用的边框做了标准化:边框样式、圆角和阴影各自提供固定的一组选项,并且全部以 CSS 变量的形式暴露。本文按这份规范说明:先认识规范里定义了哪些变量,再在自己的组件中引用它们,最后说明当设计规范要求的数值与库默认值不一致时的两种覆盖方式,以及如何验证覆盖生效。

规范定义了哪些边框、圆角与阴影变量

Border 设计文档 给出的三组标准样式是:

边框样式(见 border.vue 示例代码)只有两种:

样式粗细与写法颜色来源
Solid1px solidvar(--el-border-color)
Dashed2px dashedvar(--el-border-color)

圆角(见 radius.vue)提供 4 档,对应 CSS 变量分别为:

档位CSS 变量
No Radius0px(不引用变量)
Small Radiusvar(--el-border-radius-small)
Large Radius(base)var(--el-border-radius-base)
Round Radiusvar(--el-border-radius-round)

阴影(见 shadow.vue)提供 4 档:

档位CSS 变量
Basic Shadowvar(--el-box-shadow)
Light Shadowvar(--el-box-shadow-light)
Lighter Shadowvar(--el-box-shadow-lighter)
Dark Shadowvar(--el-box-shadow-dark)

这些变量在编译时由 SCSS 定义生成。默认值位于 var.scss:

  • $border-color是一个 map:''#dcdfe6,另有lightlighterextra-lightdarkdarker各档;$border-width1px$border-stylesolid
  • $border-radiusbase: 4pxsmall: 2pxround: 20pxcircle: 100%
  • $box-shadow:base 为0px 12px 32px 4px rgba(0,0,0,0.04), 0px 8px 20px rgba(0,0,0,0.08)light0px 0px 12px rgba(0,0,0,0.12)lighter0px 0px 6px rgba(0,0,0,0.12)dark为三条阴影叠加(0px 16px 48px 16px rgba(0,0,0,0.08)等)。

Theming 文档 说明这些 SCSS 变量会通过 SCSS 函数自动转换为 CSS 变量,所以组件与自定义样式统一引用var(--el-...)即可,不需要各自硬编码数值。Design 文档 中的一致性原则("all elements should be consistent")是这套规范的目标:所有元素使用同一组设计变量,避免出现页面内不一致的边框、圆角与阴影。

在自己的组件中引用规范变量

最直接的统一方式:自定义元素的样式只引用上述变量,而不写具体数值。下面是与官方示例一致的写法:

/* 边框:1px 实线 / 2px 虚线 */ .my-card { border: 1px solid var(--el-border-color); } .my-divider { border-top: 2px dashed var(--el-border-color); } /* 圆角:按规范档位选取 */ .my-card { border-radius: var(--el-border-radius-base); } /* 阴影:弹层类元素用 base,悬停浮层用 light */ .my-dialog { box-shadow: var(--el-box-shadow); }

需要说明:--el-border-color--el-border-radius-*--el-box-shadow*属于 common 级别的公共变量,示例代码(border.vue、radius.vue、shadow.vue)本身就是用它们渲染的。Theming 文档也提示,各组件级 CSS 变量名的说明未来会补充到各组件文档中,因此组件私有变量请以当前版本源码为准,不要凭名称猜测。

设计规范要求的数值与库默认值不一致时

Theming 文档给出两种覆盖方式,按是否需要运行时生效选择。

方式一:CSS 变量(运行时,无需重新编译 SCSS)

全局生效:

:root { --el-border-radius-base: 6px; }

Theming 文档建议:出于性能考虑,优先把变量挂在某个类下,而不是全局:root——只影响使用该类的作用域:

.custom-class { --el-border-radius-base: 6px; --el-box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); }

如果由脚本控制,文档给出的读/写方式是:

const el = document.documentElement // 读取 getComputedStyle(el).getPropertyValue(`--el-color-primary`) // 写入 el.style['--el-border-radius-base'] = '6px'

文档同时推荐 VueUse 的useCssVar作为更便捷的方式,radius 示例中也用到了它。CSS 变量方式的优点是"可以动态修改变量,而无需修改 scss 并重新编译"。

方式二:SCSS 变量(编译期,整体替换主题变量)

如果项目本身使用 SCSS,可以创建styles/element/index.scss,用@forward ... with (...)覆盖需要的变量。注意文档明确要求使用@use/@forward而不是@import(sass 团队将移除@import)。例如覆盖边框圆角 map:

/* styles/element/index.scss — 只覆盖需要的部分 */ @forward 'element-plus/theme-chalk/src/common/var.scss' with ( $border-radius: ( 'base': 6px, 'small': 3px, ) ); // 全量导入样式时再加: // @use "element-plus/theme-chalk/src/index.scss" as *;

然后在入口文件导入该文件(文档示例):

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)

两点限制来自 Theming 文档原文:

  1. element/index.scss必须放在 element-plus 的 scss之前导入,否则会产生 sass 变量混合的问题(因为需要用自定义变量生成 lighter 色阶)。
  2. 项目自己的 scss 要与 element 的变量 scss 分开,混在一起会导致每次热更新都要编译大量 scss 文件。

按需导入(on demand)时,vite 项目用scss.additionalData把变量文件注入每个组件样式一起编译:

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

webpack 项目对应配置见 Theming 文档中的unplugin-element-plus/webpack示例,写法相同(additionalData+ElementPlus({ useSource: true }))。

验证覆盖是否生效

  • CSS 变量方式:改动是运行时生效的,无需重新编译。可以用文档给出的读回方式核对实际值:getComputedStyle(el).getPropertyValue('--el-border-radius-base')返回的应是覆盖后的值,同时观察使用var(--el-border-radius-base)的组件渲染结果同步变化。
  • SCSS 方式:改动后需要重新编译。验证方式是确认编译产物中对应 CSS 变量的值已替换,例如 base 圆角变为覆盖值;@forward ... with只合并了你写出的 key,未覆盖的档位(如round)保持var.scss中的默认值。
  • 两种方式的判定标准相同:页面上所有引用同一变量的位置(按钮、卡片、弹层等)取值一致,而不是各元素各自硬编码。

适用范围与限制

  • 本文的变量名与默认值以 var.scss、Border 设计文档 及其示例为准;不同版本的var.scss若新增档位,以仓库当前文件为准。
  • 边框颜色只覆盖--el-border-color时,虚线与实线样式同步变化,因为两种样式引用的是同一个变量(见 border.vue)。
  • Theming 文档明确说明:组件级 CSS 变量名文档"未来会写到各组件文档中",当前版本若需要组件私有变量,直接查源码变量定义,不要凭名称推断。
  • SCSS 覆盖要求项目自身使用 SCSS 并按文档要求的顺序导入;只使用预编译 CSS 的项目只能走 CSS 变量方式。

【免费下载链接】element-plus🎉 A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询