Element Plus 默认提供一套主题,我们可以通过修改SCSS 变量来覆盖样式
-
Sass 模块系统 (
@use)@use 'sass:math'; @use 'sass:map'; @use 'sass:color'; @use '../mixins/function.scss' as *;@use 'sass:math';: 引入 Sass 的数学模块,允许进行算术运算,例如在set-color-mix-levelmixin 中看到的math.div()和math.percentage(),用于精确计算颜色混合的百分比。@use 'sass:map';: 引入 Sass 的 Map (关联数组) 模块。这是 Element Plus 主题系统中最为核心的功能之一。通过map.get()、map.deep-merge()和map.merge()等函数,可以方便地定义、获取和合并复杂的颜色、字体、边框等样式变量集合。例如$colors、$font-size等都是通过 Map 来管理的。@use 'sass:color';: 引入 Sass 的颜色模块,提供了强大的颜色操作函数,如color.mix()用于混合两种颜色,生成不同深浅的色阶(例如 primary color 的 light-* 和 dark-* 系列)。@use '../mixins/function.scss' as \*;: 导入自定义的 mixins 和 functions。as *的用法表示将该模块下的所有成员(mixins 和 functions)导入到当前命名空间,可以直接使用,例如getCssVar()函数。
@use规则取代了旧的@import规则,它提供了更好的命名空间管理,避免了全局变量和选择器冲突,使得样式代码更加健壮和可维护。 -
变量系统(
$variable) 与默认值!default机制sass 变量是定义可复用值的基本方式,例如颜色、字体栈或任何 CSS 值。
$types: primary, success, warning, danger, error, info; $border-width: 1px !default; $border-style: solid !default;$types: 这是一个 Sass 列表 (List),存储了系统中定义的主要状态类型。它常用于@each循环中,为每种类型生成对应的样式。!default标志: 这个标志非常重要。它意味着如果该变量尚未被赋值,则使用当前这个值;如果它已经被外部(例如用户自定义的主题文件)赋值,则当前这条赋值语句将被忽略。这为 Element Plus 的主题定制提供了极大的灵活性,用户可以在不修改源码的情况下覆盖默认变量值。几乎所有的基础颜色、尺寸、边框等变量都使用了!default。 -
Maps:结构化数据管理
Maps 是 Sass 中用于组织和访问键值对数据的强大工具。Element Plus 大量使用 Maps 来定义组件的各种样式属性。
$colors: () !default; $colors: map.deep-merge( ( 'white': #ffffff, 'black': #000000, 'primary': ( 'base': #409eff, ), // ...其他颜色 ), $colors ); $font-size: () !default; $font-size: map.merge( ( 'extra-large': 20px, // ...其他字号 ), $font-size );初始化与合并: 通常先将 Map 初始化为空
()并配合!default,然后使用map.deep-merge()或map.merge()来合并基础定义和可能的外部$colors覆盖。map.deep-merge()可以递归合并嵌套的 Map,而map.merge()只合并顶层。访问: 使用
map.get($map, $key1, $key2, ...)来获取 Map 中的值。例如map.get($colors, 'primary', 'base')获取$colorsMap 中primary键下的base键对应的值。组件化变量: 文件中大量的组件特定变量,如
$checkbox、$radio、$button等,都是通过 Map 定义的。这种方式使得组件的样式属性集中管理,结构清晰。 -
Mixins (
@mixin和@include):代码复用与抽象Mixins 允许开发者定义可重用的 CSS 声明块。这对于生成重复模式的样式(如颜色变体)非常有用。
@mixin set-color-mix-level( $type, $number, $mode: 'light', $mix-color: $color-white ) { $colors: map.deep-merge( ( $type: ( '#{$mode}-#{$number}': color.mix( $mix-color, map.get($colors, $type, 'base'), math.percentage(math.div($number, 10)) ), ), ), $colors ) !global; // 注意这里的 !global } // 使用 mixin @each $type in $types { @for $i from 1 through 9 { @include set-color-mix-level($type, $i, 'light', $color-white); } }参数化:
set-color-mix-levelmixin 接受$type(如 'primary')、$number(1-9)、$mode('light' 或 'dark') 和$mix-color(与白色或黑色混合) 作为参数。动态生成: 它动态地计算出新的颜色值,并将其合并到全局的
$colorsMap 中。!global标志: 在 mixin 内部修改一个在 mixin 外部定义的变量(如此处的$colors),需要使用!global标志。这是一个需要谨慎使用的特性,但在这种动态生成主题色的场景下是合理的。插值 (
#{}): 在选择器或属性名中使用变量时,需要使用插值,例如'#{$mode}-#{$number}'。 -
控制指令 (
@each,@for):自动化样式生成
Sass 的控制指令使得基于变量和逻辑生成大量 CSS 规则成为可能。
-
@each $item in $list:@each $type in $types { // ... 为每种类型生成颜色变体 @for $i from 1 through 9 { @include set-color-mix-level($type, $i, 'light', $color-white); } @include set-color-mix-level($type, 2, 'dark', $color-black); }这里,
@each遍历$types列表中的每一种颜色类型('primary', 'success' 等)。 -
@for $var from <start> through <end>:嵌套在
@each循环内部的@for循环从 1 到 9,为每种主色生成 9 个亮色阶 (light-1到light-9)。
这些循环与 set-color-mix-level mixin 结合,极大地减少了手动编写相似颜色声明的重复劳动,并确保了颜色系统的一致性。
-
函数 (
function):自定义逻辑与值转换虽然
var.scss主要依赖内建函数,但它也通过@use '../mixins/function.scss' as *;引入了自定义函数。其中一个关键的自定义函数是getCssVar()。$border-color-hover: getCssVar('text-color', 'disabled') !default;getCssVar()用于生成 CSS 自定义属性 (CSS Variables) 的字符串表示,例如var(--el-text-color-disabled)。这使得 Element Plus 能够同时利用 Sass 的预处理能力和 CSS 自定义属性的运行时动态性。Sass 变量在编译时确定,而 CSS 自定义属性可以在浏览器运行时被 JavaScript 修改或根据其他 CSS 规则改变。例如,
getCssVar('text-color', 'disabled')会被编译成var(--el-text-color-disabled)。// joinVarName(('button', 'text-color')) => '--el-button-text-color',这里的el可以通过namespace修改 @function joinVarName($list) { $name: '--' + config.$namespace; @each $item in $list { @if $item != '' { $name: $name + '-' + $item; } } @return $name; } // getCssVar('button', 'text-color') => var(--el-button-text-color) @function getCssVar($args...) { @return var(#{joinVarName($args)}); } -
组件变量的结构化管理
$checkbox: () !default; $checkbox: map.merge( ( 'font-size': 14px, 'font-weight': getCssVar('font-weight-primary'), 'text-color': getCssVar('text-color-regular'), // ... ), $checkbox );对于每个UI组件,Element Plus都定义了专门的变量映射,包含该组件的所有可配置属性。这种结构化管理方式有几个优势:
- 变量命名空间隔离,避免冲突
- 通过 getCssVar 函数引用全局变量,保持一致性
- 支持组件级别的主题定制
-
响应式设计变量系统
$sm: 768px !default; // ... 其他断点 $breakpoints: ( 'xs': '(max-width: #{$sm - 1})', 'sm': '(min-width: #{$sm})', // ... ) !default;这些变量和 Map 可以在其他 SCSS 文件中与
@media规则结合使用,以创建响应式的布局和组件样式。$button-padding-vertical: () !default; $button-padding-vertical: map.merge( ( 'large': 13px, 'default': 9px, 'small': 6px, ), $button-padding-vertical );通过为不同尺寸定义对应的属性值,Element Plus实现了组件的响应式设计。这种方法使得组件可以根据不同场景(大、中、小尺寸)呈现适当的视觉效果,同时保持设计的一致性。