【第1743期】Element-UI 技术揭秘 - 色彩、字体、边框与图标
收藏

前言

Element-UI 技术揭秘系列来了。今日早读文章由Zoom架构师@黄轶授权分享。

公众号后台回复关键词 黄轶 查看专栏内容

正文从这开始~~

element-ui 组件库之所以受欢迎,除了组件丰富,文档友好之外,还得益于它的精美的设计。之前在组件库的整体设计文章中提到,element-ui 背后有一只强大的设计团队,他们为组件库了制定了一套设计规范。

需求分析

当我们去设计一套组件库的时候,首先要考虑颜色、字体、边框、图标这些基础元素的设计,它们是构建各个组件的基石,如果没有做好这些基础设计,那么做出来的组件库看上去一定很山寨。

这些基础设计都需要遵循一定的设计规范,经验丰富的设计师在设计的时候会制定一套规范,那作为程序员的我们在实现这套设计规范的时候,在代码层面也可以遵循一定的规范。

设计与实现

那么接下来,我们从代码的角度依次来介绍这四个基础元素在的设计与实现。

色彩

Element 为了避免视觉传达差异,使用一套特定的调色板来规定颜色,为你所搭建的产品提供一致的外观视觉感受。

主色

Element 主要品牌颜色是鲜艳、友好的蓝色。

如图所示,element-ui 提供了一套蓝色系的颜色,可以看到除了主色 #409EFF 之外,还有一系列渐变的蓝色,那么在代码中是如何实现的呢?

element-ui 关于颜色的定义在 packages/theme-chalk/src/common/var.scss 中:

  1. $--color-primary: #409EFF !default;

这里定义了 $--color-primary 变量,值为 #409EFF,注意这里用了 !default 关键字,它在这里的含义是如果外面已经定义了 $--color-primary,那么就用已经定义的值,否则赋值为 #409EFF。这么做的原因应该是和自定义主题色相关,如果用户定义了新的主题色,该变量就可以指向新的主题颜色。对于主题蓝色的渐变色,element-ui 的实现如下:

  1. $--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */

  2. $--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */

  3. $--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */

  4. $--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */

  5. $--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */

  6. $--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */

  7. $--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */

  8. $--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */

  9. $--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */

这里定义了 9 个变量,都使用了 mix 函数,mix 函数是 sass 中内置的函数,它表示 2 种颜色的混合,第三个参数表示 2 种颜色混合各自占的比例,以 mix($--color-white,$--color-primary, 10%) 为例,表示 $--color-white(白色)占比 10%,而 $--color-primary(主色)占比 90%。通过这种方式,element-ui 轻松实现了不同颜色深度的主色。

辅助色

除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。

这些辅助色的实现也是大同小异,我们以成功色为例,其余不再赘述。

  1. $--color-success: #67C23A !default;


  2. $--color-success-light: mix($--color-white, $--color-success, 80%) !default;

  3. $--color-success-lighter: mix($--color-white, $--color-success, 90%) !default;

也是通过 mix 混入白色的方式,生成不同颜色深度的成功色。

中性色

中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。

关于文本颜色,由深到浅定义了四个变量:

  1. /// color|1|Font Color|2

  2. $--color-text-primary: #303133 !default;

  3. /// color|1|Font Color|2

  4. $--color-text-regular: #606266 !default;

  5. /// color|1|Font Color|2

  6. $--color-text-secondary: #909399 !default;

  7. /// color|1|Font Color|2

  8. $--color-text-placeholder: #C0C4CC !default;

关于边框颜色,由深到浅定义了四个变量:

  1. /// color|1|Border Color|3

  2. $--border-color-base: #DCDFE6 !default;

  3. /// color|1|Border Color|3

  4. $--border-color-light: #E4E7ED !default;

  5. /// color|1|Border Color|3

  6. $--border-color-lighter: #EBEEF5 !default;

  7. /// color|1|Border Color|3

  8. $--border-color-extra-light: #F2F6FC !default;

关于背景色,定义了三个变量:

  1. /// color|1|Background Color|4

  2. $--color-black: #000000 !default;

  3. /// color|1|Background Color|4

  4. $--color-white: #FFFFFF !default;

  5. /// color|1|Background Color|4

  6. $--background-color-base: #F5F7FA !default;

注意这里的第三个变量和图中透明色表示不同,因为透明背景理论上是不需要配置 background 的,默认就是透明的。这里第三个变量也表示一种基础白色,在多个组件中使用。

字体

element-ui 对字体进行统一规范,力求在各个操作系统下都有最佳展示效果。

图中展示了多种字体的样式,其中有我们 mac 用户比较熟悉的 PingFang SC,还有一些 win 用户熟悉的 MicroSoft YaHei。

在 packages/theme-chalk/src/reset.scss 中定义了全局的字体样式:

  1. body {

  2. font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;

  3. font-weight: 400;

  4. font-size: $--font-size-base;

  5. color: $--color-black;

  6. -webkit-font-smoothing: antialiased;

  7. }

我们知道 font-family 可以指定一个字体列表,属性值用逗号隔开,浏览器会选择列表中第一个该计算机上有安装的字体。

字号

element-ui 定义了 6 种大小的字体,它们的定义在 packages/theme-chalk/src/common/var.scss 中:

  1. /// fontSize|1|Font Size|0

  2. $--font-size-extra-large: 20px !default;

  3. /// fontSize|1|Font Size|0

  4. $--font-size-large: 18px !default;

  5. /// fontSize|1|Font Size|0

  6. $--font-size-medium: 16px !default;

  7. /// fontSize|1|Font Size|0

  8. $--font-size-base: 14px !default;

  9. /// fontSize|1|Font Size|0

  10. $--font-size-small: 13px !default;

  11. /// fontSize|1|Font Size|0

  12. $--font-size-extra-small: 12px !default;

其中最小是 12px,最大是 20px。通常在设计是不建议出现小于 12px 大小的字体的,太小的字体会对视力不好的人群是不友好的。

行高

如图所示,通常我们在遇到多行文字的时候,设置不同的 line-height 会有不同的渲染效果,一般设置至少为 1.5。这将有助于改善低可视条件下的体验,也对认知阻碍者(如阅读困难者)有帮助。

element-ui 在 packages/theme-chalk/src/common/var.scss 中只定义了 2 种行高:

  1. /// fontLineHeight|1|Line Height|2

  2. $--font-line-height-primary: 24px !default;

  3. /// fontLineHeight|1|Line Height|2

  4. $--font-line-height-secondary: 16px !default;

element-ui 在大部分组件的实现中直接写死了行高的大小,不过通常更好的方式是使用无单位的值而不是具体的大小,因为一旦你更改了字体大小,如果用无单位值就不需要再手动改行高了。另外一特定场景是如果文字的大小要随页面的缩放而变化,使用无单位的值可以确保行高也会等比例缩放。

边框

element-ui 对边框进行统一规范,可用于按钮、卡片、弹窗等组件里。

边框和圆角

element-ui 提供了一系列关于边框的圆角样式的定义,在 packages/theme-chalk/src/common/var.scss 中:

  1. /// color|1|Border Color|3

  2. $--border-color-base: #DCDFE6 !default;

  3. /// color|1|Border Color|3

  4. $--border-color-light: #E4E7ED !default;

  5. /// color|1|Border Color|3

  6. $--border-color-lighter: #EBEEF5 !default;

  7. /// color|1|Border Color|3

  8. $--border-color-extra-light: #F2F6FC !default;


  9. $--border-width-base: 1px !default;

  10. $--border-style-base: solid !default;

  11. $--border-color-hover: $--color-text-placeholder !default;

  12. $--border-base: $--border-width-base $--border-style-base $--border-color-base !default;

  13. /// borderRadius|1|Radius|0

  14. $--border-radius-base: 4px !default;

  15. /// borderRadius|1|Radius|0

  16. $--border-radius-small: 2px !default;

  17. /// borderRadius|1|Radius|0

  18. $--border-radius-circle: 100% !default;

  19. /// borderRadius|1|Radius|0

  20. $--border-radius-zero: 0 !default;s

其中包括了边框的粗细、颜色、样式,圆角大小等变量,还包括了 hover 的颜色,用在组件中。

投影

element-ui 提供了几种常用的投影方式,定义在 packages/theme-chalk/src/common/var.scss 中:

  1. /// boxShadow|1|Shadow|1

  2. $--box-shadow-base: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04) !default;

  3. // boxShadow|1|Shadow|1

  4. $--box-shadow-dark: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .12) !default;

  5. /// boxShadow|1|Shadow|1

  6. $--box-shadow-light: 0 2px 12px 0 rgba(0, 0, 0, 0.1) !default;

如果对 box-shadow 相关属性值不太理解的同学,可以去 mdn 上自行查阅相关资料学习;也可以在线调试它的属性值,看看不同的渲染效果。

图标

element-ui 提供了一套常用的图标集合。

使用方法

直接通过设置类名为 el-icon-iconName 来使用即可。例如:

对应代码:

  1. <i class="el-icon-edit"></i>

  2. <i class="el-icon-share"></i>

  3. <i class="el-icon-delete"></i>

  4. <el-button type="primary" icon="el-icon-search">搜索</el-button>

我们只需要简单设置类名即可引入这些字体图标了(关于 button 的实现下一篇文章会提到),这是如何做到的呢?

实现方式

其实 element-ui 提供的图标是利用 IconFont 技术实现的,在 packages/theme-chalk/src/icon.scss 中定义:

  1. @font-face {

  2. font-family: 'element-icons';

  3. src: url('#{$--font-path}/element-icons.woff') format('woff'), /* chrome, firefox */

  4. url('#{$--font-path}/element-icons.ttf') format('truetype'); /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/

  5. font-weight: normal;

  6. font-display: $--font-display;

  7. font-style: normal;

  8. }


  9. [class^="el-icon-"], [class*=" el-icon-"] {

  10. /* use !important to prevent issues with browser extensions that change fonts */

  11. font-family: 'element-icons' !important;

  12. speak: none;

  13. font-style: normal;

  14. font-weight: normal;

  15. font-variant: normal;

  16. text-transform: none;

  17. line-height: 1;

  18. vertical-align: baseline;

  19. display: inline-block;


  20. /* Better Font Rendering =========== */

  21. -webkit-font-smoothing: antialiased;

  22. -moz-osx-font-smoothing: grayscale;

  23. }


  24. .el-icon-edit:before {

  25. content: "\e78c";

  26. }


  27. // ...

首先,利用 @font-face 定义了自定义字体,它的来源是 packages/theme-chalk/src/fonts/ 目录中定义的字体图标文件。

其次,利用属性选择器筛选了以 el-icon- 开头或者是带有 el-icon- 的类名的元素,它们对应的 font-family 就是自定义字体 element-icons。

然后对应不同的图标,定义不同的 el-icon-xxx 类名,并通过 before 伪类指定对应的 content 值,这样用户只需要使用 el-icon-xxx 的类名就可以引用相应的图标。

最后推荐 2 个制作字体图标库的网站,Iconfont 和 icomoon。

总结

这篇文章总体来说还是很简单的,对于设计师提供的设计规范,element-ui 主要的实现方式是在公共的 sass 文件中定义了很多变量,未来组件中的样式就会引入这些变量,相当于编程的方式去书写 CSS,而不会在每个组件内部去写死字体、颜色、边框的值。这样的好处不仅语义化强,而且维护性好,一旦这些基础元素的设计改变,我可以只去修改这些变量值就可以,而不用去修改组件,另外对于组件整体的自定义主题设计也是提供了非常大的便利。

学习完这篇文章,你也可以在自己的项目中尝试去定义公共的样式文件和变量,然后在组件中去引入它们。当然如果你的组件库支持了后编译,你甚至可以直接去引入组件库中定义的变量。

关于本文 作者:@黄轶 原文:https://mp.weixin.qq.com/s/dZMNvjXxy6fB6JuMXJVRPg

为你推荐


【第1458期】ElementUI的构建流程


【第1106期】Element 中的键盘可访问性