news 2026/8/11 10:59:09

Vue3 还原一个企业级后台-04-设计系统建设

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue3 还原一个企业级后台-04-设计系统建设

设计系统:从设计稿到 CSS 变量

设计系统不是"把设计稿里的颜色抄一遍"。它是设计稿与代码之间的翻译层——一次定义,全局生效,改一个变量就能换肤。这篇文章,把从 Design Token 到 CSS 变量再到 Element Plus 主题覆写的完整链路理清楚。


一、为什么 17 个 Frame 需要一套设计系统

在上一篇文章里,我从 Figma 中提取出了颜色、字体、圆角、间距等设计属性。但提取只是第一步——如果直接把这些值写死在每个组件里,会发生什么?

假设主色#0073FB出现在了 17 个 Frame 的 80+ 处节点上。按"看到什么写什么"的直觉做法,你的代码里会出现几十次color: #0073FBbackground: #0073FBborder-color: #0073FB

然后有一天,设计师说:“主色调调浅一点,改成#1A8CFF。”

你打开 VS Code,全局搜索#0073FB,替换为#1A8CFF。运气好的话改了 40 处没出问题。运气不好的话,某个恰好也是#0073FB但不是主色的边框被你一起改掉了——这种 Bug 等你发现的时候,可能已经上线一周了。

这不是假设。我在之前的项目里亲身经历过一次"改主题色"的噩梦。从那以后,我给自己定了一条铁律:

任何在项目中重复出现 2 次以上的样式值,必须定义为变量。

这不是过度工程化,这是对自己的仁慈。

对于"管网模型工具"这个项目,17 个 Frame 的样式看起来眼花缭乱,但经过上一篇的去重归并后,真正的系统色只有 10 个左右,字号只有 4 个阶梯,圆角只有 4 个阶梯。这些数值不是散落的——它们构成了一套隐式的设计规范。我要做的,是把这套隐式规范"显式化"。


二、设计 Token 的五维分类

设计 Token 这个词听起来高大上,但本质上就是"给样式值起个有意义的名字"。我把这个项目涉及的 Token 分了五个维度:

2.1 颜色 Token

颜色是最容易失控的维度。17 个 Frame 里看起来有 50+ 种颜色,但实际上:

  • 有些是同一个颜色在不同透明度下的表现(比如主色#0073FB降低 10% 透明度做 hover 态)
  • 有些是同一个颜色在不同节点上的重复引用
  • 有些是渐变叠加后的渲染色,不是源色

去重归并后,真正的系统色如下:

Token 名称色值语义使用场景
--color-bg-page#C8E1FF页面底色登录页背景、内容区底色
--color-bg-card#F0F5FC卡片/容器背景顶栏、侧栏、信息卡片
--color-bg-white#FFFFFF纯白背景弹窗、表格、表单内部
--color-primary#0073FB主色/品牌色主按钮、选中态、链接、图标高亮
--color-primary-hover#005FCF主色悬停按钮 hover、菜单 hover
--color-primary-light#E8F1FE主色浅底选中行背景、标签背景
--color-success#52C41A成功/启用状态标签-启用、成功提示
--color-danger#FF4D4F危险/删除删除按钮、禁用状态
--color-text-primary#333333主文字色标题、正文、表格内容
--color-text-secondary#666666次要文字辅助说明、标签、描述
--color-text-placeholder#999999占位/禁用文字输入框 placeholder、禁用态文字
--color-border#D9D9D9边框色表格线、输入框边框、分割线

为什么要区分--color-text-primary--color-text-secondary?举个例子:一个表单里,字段标签用#333333,辅助说明用#666666。如果直接写色值,后来设计师说"辅助说明再淡一点,改成#888888",你又要全局搜索。定义成变量后,只需改一处。

2.2 字体 Token

这个项目涉及三种字体:MiSans(中文)、AlibabaPuHuiTi(中文标题)、Inter(英文/数字)。但用户设备上不一定安装了这些字体,所以需要完整的降级策略:

Token 名称
--font-family-base"MiSans", "PingFang SC", "Microsoft YaHei", sans-serif
--font-family-title"AlibabaPuHuiTi", "MiSans", "PingFang SC", sans-serif
--font-family-number"Inter", -apple-system, "Segoe UI", sans-serif

2.3 字号阶梯

17 个 Frame 中字号并非随意取值,而是有明显的阶梯规律:

Token 名称数值使用场景
--font-size-xl26px登录页大标题、页面级标题
--font-size-lg18px模块标题、卡片标题
--font-size-md16px正文、表格内容、输入框文字
--font-size-sm14px辅助文字、标签、提示信息
--font-size-xs12px注释、徽标、次要元数据

注意,这不是"随便挑了 5 个字号"——这些值直接来自 Figma 中所有 TEXT 节点的fontSize字段统计结果。没有出现 13px、15px、17px 这样的奇数尺寸,也没有出现 20px、22px 这样不在阶梯内的值。这说明设计师遵循了一套清晰的字号规范,我只是把它翻译成了变量名。

2.4 圆角阶梯

Token 名称数值使用场景
--radius-lg14px卡片、弹窗、大型容器
--radius-md10px输入框、下拉菜单、表格
--radius-sm8px标签、徽标、小按钮
--radius-xs6px微小元素(tooltip、badge)

这四个值有一个共同点:都是偶数。这不是巧合——偶数值在 Retina 屏幕上渲染时不会出现半像素模糊。好的设计师会在这种细节上体现专业性。

2.5 间距阶梯

间距是设计中"最不起眼但最影响精致度"的维度。这个项目的间距体系是严格的 4px 基准体系:

--spacing-xs:4px;--spacing-sm:8px;--spacing-md:12px;--spacing-lg:16px;--spacing-xl:24px;--spacing-2xl:32px;--spacing-3xl:40px;--spacing-4xl:50px;

你会发现:4 × 2 = 84 × 3 = 124 × 4 = 16……除50px外,所有间距都是 4 的倍数。这遵循了设计界的"4px 基准网格"原则,确保所有元素对齐在同一个不可见的网格上,视觉上整齐而不杂乱。


三、tokens.css:把 Token 写成代码

有了 Token 定义,下一步就是把它写成真正的 CSS。我创建了src/styles/tokens.css

/* ======================================== 设计系统 · Design Tokens 基于 Figma "管网模型工具" 设计稿提取 ======================================== */:root{/* ── 颜色:背景 ── */--color-bg-page:#C8E1FF;--color-bg-card:#F0F5FC;--color-bg-white:#FFFFFF;/* ── 颜色:品牌/功能 ── */--color-primary:#0073FB;--color-primary-hover:#005FCF;--color-primary-light:#E8F1FE;--color-success:#52C41A;--color-danger:#FF4D4F;/* ── 颜色:文字 ── */--color-text-primary:#333333;--color-text-secondary:#666666;--color-text-placeholder:#999999;/* ── 颜色:边框/分割 ── */--color-border:#D9D9D9;/* ── 字体:家族 ── */--font-family-base:"MiSans","PingFang SC","Microsoft YaHei",sans-serif;--font-family-title:"AlibabaPuHuiTi","MiSans","PingFang SC",sans-serif;--font-family-number:"Inter",-apple-system,"Segoe UI",sans-serif;/* ── 字体:字号 ── */--font-size-xs:12px;--font-size-sm:14px;--font-size-md:16px;--font-size-lg:18px;--font-size-xl:26px;/* ── 字体:行高 ── */--line-height-tight:1.2;--line-height-normal:1.5;--line-height-loose:1.8;/* ── 圆角 ── */--radius-xs:6px;--radius-sm:8px;--radius-md:10px;--radius-lg:14px;/* ── 间距(4px 基准网格) ── */--spacing-xs:4px;--spacing-sm:8px;--spacing-md:12px;--spacing-lg:16px;--spacing-xl:24px;--spacing-2xl:32px;--spacing-3xl:40px;--spacing-4xl:50px;/* ── 阴影 ── */--shadow-card:0 2px 8pxrgba(0,0,0,0.08);--shadow-dialog:0 4px 16pxrgba(0,0,0,0.12);--shadow-selected:0 0 0 2pxvar(--color-primary-light);/* ── 过渡动画 ── */--transition-fast:0.15s ease;--transition-normal:0.3s ease;/* ── 布局 ── */--layout-topbar-height:120px;--layout-sidenav-width:200px;--layout-content-padding:24px;}

这里有几个设计决策值得展开:

1. 阴影也定义为 Token

Figma 中卡片有0 2px 8px rgba(0,0,0,0.08)的投影,弹窗有稍重的0 4px 16px rgba(0,0,0,0.12)。如果不定义为 Token,很容易出现"这个弹窗的阴影比另一个深一点"的不一致问题。

2. 布局尺寸也纳入 Token

顶栏高度 120px、侧栏宽度 200px——这些值在多个布局组件中会反复引用。把它们定义为 Token,改布局时只需要改一个地方。

3. 过渡动画统一

所有交互(hover、展开、切换)使用相同的缓动曲线和时长。用户感知到的"流畅度"很大程度上取决于动画的一致性。


四、Element Plus 主题覆写:让组件库听话

设计 Token 定义好了,但 Element Plus 组件有自己的默认样式——蓝色主色是#409EFF,圆角是3px,和我们的设计稿完全不同。

要让 Element Plus"穿"上我们的设计系统,需要做两级覆写。

4.1 理解 Element Plus 的样式变量体系

Element Plus 2.x 使用 CSS 变量来控制主题,所有变量都以--el-开头。官方文档列出了 100+ 个可覆写的变量,但实际项目中不需要全改。核心变量就这些:

Element Plus 变量说明
--el-color-primary主色
--el-color-primary-light-3~light-9主色的浅色变体
--el-border-radius-base默认圆角
--el-font-size-base默认字号
--el-text-color-primary主文字色
--el-text-color-regular常规文字色
--el-border-color-base边框色

4.2 用 SCSS 覆写

src/styles/下创建element-override.scss

/* ======================================== Element Plus 主题覆写 将 design tokens 映射到 Element Plus CSS 变量 ======================================== */ // ── 主色 ── --el-color-primary: var(--color-primary); --el-color-primary-light-3: var(--color-primary-light); --el-color-primary-light-5: var(--color-primary-light); --el-color-primary-light-7: var(--color-primary-light); --el-color-primary-light-8: var(--color-primary-light); --el-color-primary-light-9: var(--color-primary-light); --el-color-primary-dark-2: var(--color-primary-hover); // ── 文字色 ── --el-text-color-primary: var(--color-text-primary); --el-text-color-regular: var(--color-text-secondary); --el-text-color-placeholder: var(--color-text-placeholder); // ── 边框 ── --el-border-color-base: var(--color-border); --el-border-color-light: var(--color-border); // ── 圆角 ── --el-border-radius-base: var(--radius-md); --el-border-radius-small: var(--radius-sm); // ── 字号 ── --el-font-size-base: var(--font-size-md); --el-font-size-small: var(--font-size-sm); --el-font-size-extra-small: var(--font-size-xs); --el-font-size-large: var(--font-size-lg); // ── 背景 ── --el-bg-color: var(--color-bg-white); --el-bg-color-page: var(--color-bg-page);

这里有一个技术细节:Element Plus 的主色会衍生出light-3light-9九个浅色变体,用于 hover 背景、选中态背景等。如果不覆写它们,会出现"主按钮是#0073FB,但 hover 时背景变成#409EFF浅色"的诡异现象。我把它们统一映射到--color-primary-light,虽然精度上会损失一些渐变层次,但对于演示原型来说足够用了。

4.3 全局样式导入顺序

样式的导入顺序有严格要求。在main.js中:

// 1. Element Plus 默认样式(必须先加载)import'element-plus/dist/index.css'// 2. 设计 Token(定义 CSS 变量)import'@/styles/tokens.css'// 3. Element Plus 主题覆写(消费 Token 变量)import'@/styles/element-override.scss'// 4. 全局自定义样式import'@/styles/global.css'

顺序错了会有问题:如果在 Token 定义之前就覆写 Element Plus,CSS 变量找不到对应的值,会回退到浏览器默认值,整个色彩体系就乱套了。


五、字体加载方案:CDN + 本地 + 回退三级策略

字体是这个设计系统里"不可见但很重要"的一环。设计师用了 MiSans(小米字体)和 AlibabaPuHuiTi(阿里普惠体),但用户的电脑上大概率没有。

我的策略分三级:

第一级:CDN 加载(最优解)

如果字体官方提供了 CDN,优先使用。CDN 的优势是:不需要打包进项目(省体积),而且用户浏览器可能已经缓存了这些字体。

/* 在 index.html 中通过 <link> 引入,或使用 @import */@importurl('https://cdn.jsdelivr.net/npm/misans@latest/lib/Normal/MiSans-Normal.min.css');

第二级:本地打包(兜底方案)

如果 CDN 不可用(比如内网环境),将字体文件放入src/assets/fonts/,用@font-face声明:

@font-face{font-family:'MiSans';src:url('@/assets/fonts/MiSans-Normal.woff2')format('woff2'),url('@/assets/fonts/MiSans-Normal.woff')format('woff');font-weight:400;font-style:normal;font-display:swap;/* 先显示回退字体,加载完再切换 */}

第三级:系统字体回退

无论 CDN 还是本地打包,最后的font-family声明里一定带系统字体做降级:

font-family:"MiSans","PingFang SC","Microsoft YaHei",sans-serif;

这样即使用户的设备完全没有 MiSans,也能用 PingFang SC(macOS)或 Microsoft YaHei(Windows)渲染出视觉效果接近的中文。

font-display: swap也值得单独提一句:它告诉浏览器"先用回退字体渲染文字,等自定义字体下载完成后再替换"。这避免了"字体没加载完,页面白屏"的 FOIT(Flash of Invisible Text)问题。


六、设计系统的工程价值

一套设计 Token + CSS 变量 + Element Plus 覆写搭完之后,它带来的价值会随着项目推进越来越明显:

1. 改色 = 改一行的时代

设计师说"主色改成暖色系"。你打开tokens.css,改一行:

--color-primary:#FF6B35;/* 原来 #0073FB */--color-primary-hover:#E55A2B;/* 原来 #005FCF */--color-primary-light:#FFF0E8;/* 原来 #E8F1FE */

刷新页面。整个项目的所有主按钮、选中态、链接、图标高亮、标签背景——从登录页到模型发布的每一个 Frame——全部变成暖色系。一秒完成。

这就是"一次定义,全局生效"的真正含义。

2. 新页面开发成本骤降

当你开发第 8 篇的"API 注册管理"页面时,你不需要再去翻 Figma 看"表格的边框是什么颜色"、“弹窗的圆角是多少”、“间距应该用 16px 还是 24px”。这一切都在 Token 里:

<style scoped> .api-table { background: var(--color-bg-white); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: var(--spacing-xl); } .api-table .header { color: var(--color-text-primary); font-size: var(--font-size-lg); margin-bottom: var(--spacing-lg); } </style>

你写的不是"这个页面怎么设计",而是"这个页面用哪个 Token"。新页面开发变成了一场"Token 拼图"——而拼图比从零画图快得多。

3. 团队协作的语言统一

如果是多人开发,设计系统还有一个隐藏价值:统一沟通语言。

设计师说"这个按钮用主色",前端直接写var(--color-primary)。不需要问"主色是哪个色值来着?",不需要对着 Figma 取色器手动吸色。设计师和前端说的是同一套 Token 语言,沟通成本直线下降。


七、一个文件搞定:给读者的"设计系统鸡尾酒"

最后,如果你不想像我这样拆成tokens.css+element-override.scss+global.css三个文件,可以把它们合并成一个theme.css直接引入。对于个人项目或小团队来说,一个文件反而更方便维护。

我把三合一版本也放在这里,你可以根据自己的项目规模选择哪种组织方式:

/* ======================================== theme.css 设计系统 + Element Plus 覆写,一站式 放置于 src/styles/theme.css 在 main.js 中 element-plus/dist/index.css 之后引入 ======================================== */:root{/* 设计 Token */--color-bg-page:#C8E1FF;--color-bg-card:#F0F5FC;--color-bg-white:#FFFFFF;--color-primary:#0073FB;--color-primary-hover:#005FCF;--color-primary-light:#E8F1FE;--color-success:#52C41A;--color-danger:#FF4D4F;--color-text-primary:#333333;--color-text-secondary:#666666;--color-text-placeholder:#999999;--color-border:#D9D9D9;--font-family-base:"MiSans","PingFang SC","Microsoft YaHei",sans-serif;--font-family-title:"AlibabaPuHuiTi","MiSans","PingFang SC",sans-serif;--font-family-number:"Inter",-apple-system,"Segoe UI",sans-serif;--font-size-xs:12px;--font-size-sm:14px;--font-size-md:16px;--font-size-lg:18px;--font-size-xl:26px;--line-height-tight:1.2;--line-height-normal:1.5;--line-height-loose:1.8;--radius-xs:6px;--radius-sm:8px;--radius-md:10px;--radius-lg:14px;--spacing-xs:4px;--spacing-sm:8px;--spacing-md:12px;--spacing-lg:16px;--spacing-xl:24px;--spacing-2xl:32px;--spacing-3xl:40px;--spacing-4xl:50px;--shadow-card:0 2px 8pxrgba(0,0,0,0.08);--shadow-dialog:0 4px 16pxrgba(0,0,0,0.12);--shadow-selected:0 0 0 2pxvar(--color-primary-light);--transition-fast:0.15s ease;--transition-normal:0.3s ease;--layout-topbar-height:120px;--layout-sidenav-width:200px;--layout-content-padding:24px;/* Element Plus 覆写 */--el-color-primary:var(--color-primary);--el-color-primary-light-3:var(--color-primary-light);--el-color-primary-light-5:var(--color-primary-light);--el-color-primary-light-7:var(--color-primary-light);--el-color-primary-light-8:var(--color-primary-light);--el-color-primary-light-9:var(--color-primary-light);--el-color-primary-dark-2:var(--color-primary-hover);--el-text-color-primary:var(--color-text-primary);--el-text-color-regular:var(--color-text-secondary);--el-text-color-placeholder:var(--color-text-placeholder);--el-border-color-base:var(--color-border);--el-border-color-light:var(--color-border);--el-border-radius-base:var(--radius-md);--el-border-radius-small:var(--radius-sm);--el-font-size-base:var(--font-size-md);--el-font-size-small:var(--font-size-sm);--el-font-size-extra-small:var(--font-size-xs);--el-font-size-large:var(--font-size-lg);--el-bg-color:var(--color-bg-white);--el-bg-color-page:var(--color-bg-page);}

八、小结:设计系统是"可维护性"的入场券

如果说上一篇的"读 Figma"是从混沌中提取秩序,那这一篇的"搭设计系统"就是把那个秩序固化下来。

它不会让你的页面立刻变好看——Token 本身不是视觉效果,它只是变量的名字。但它是整个项目可维护性的基础。没有它,你每写一个颜色都要犹豫"是这个色值吗",改一个色值要担心"会不会影响其他地方"。

设计系统的价值不在"写"的那一刻,而在"改"的那一刻。

Token → CSS 变量 → Element Plus 覆写,这三层下来,你的项目就拥有了一套完整的"翻译系统":设计师的语言通过 Figma 进入 Token,Token 通过 CSS 变量进入组件,组件通过覆写进入 Element Plus。从此以后,"还原设计稿"不是一场手工作坊式的复制粘贴,而是一次工程化的映射。


上一篇:03 - Figma 数据提取:用 MCP 工具读懂设计稿

下一篇预告:设计系统就位了,下一步是什么?搭脚手架——用 Vite 5 分钟搭出标准项目结构,把 Token、路由、状态管理、Mock 数据全部各就各位。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/11 10:57:41

车载音响CE认证技术解读:指令框架与EMC测试要点

一、车载音响CE认证的指令框架 车载音响&#xff08;Car Audio&#xff09;作为售后市场销售的电子设备&#xff0c;进入欧盟市场须通过CE认证。CE认证并非单一认证&#xff0c;而是依据产品功能特征匹配适用的欧盟指令组合。 #mermaid-svg-K5xWuI4ajt0qGjRn{font-family:"…

作者头像 李华
网站建设 2026/8/11 10:54:04

WSL2深度学习训练性能优化全攻略

1. WSL环境下神经网络训练的性能瓶颈分析第一次在WSL里跑ResNet-50训练时&#xff0c;我发现epoch时间比原生Linux系统慢了近40%。通过nvidia-smi观察到GPU利用率始终在60%左右徘徊&#xff0c;而显存占用却显示充足。这种矛盾现象揭示了WSL特有的性能陷阱——看似资源充足&…

作者头像 李华
网站建设 2026/8/11 10:52:28

Translumo终极指南:5步掌握专业级实时屏幕翻译技巧

Translumo终极指南&#xff1a;5步掌握专业级实时屏幕翻译技巧 【免费下载链接】Translumo Advanced real-time screen translator for games, hardcoded subtitles in videos, static text and etc. 项目地址: https://gitcode.com/gh_mirrors/tr/Translumo 还在为外语…

作者头像 李华
网站建设 2026/8/11 10:50:45

YOLOv8 单类目标检测涨点实战|1510 张锤子 VOC/YOLO 双标注数据集调优,工厂五金智能盘点、工地工具管控落地全流程

目录 一、工业制造 / 基建行业落地背景 二、锤子目标检测数据集全方位深度解析 2.1 数据集完整基础信息 2.2 锤子检测四大核心识别难点 三、YOLOv8 单类中等样本专属涨点调参体系 3.1 YOLOv8 适配五金工具核心优势 3.2 锤子场景精细化全套训练参数 3.2.1 基础硬件与尺度…

作者头像 李华
网站建设 2026/8/11 10:49:52

开源神器LinkSwift:一键获取九大网盘直链下载的终极指南

开源神器LinkSwift&#xff1a;一键获取九大网盘直链下载的终极指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天…

作者头像 李华
网站建设 2026/8/11 10:48:49

SpringBoot+Vue在线考试系统:1小时快速部署与全栈实践指南

这次我们来看一个面向学生和初学者的实战项目&#xff1a;一个基于 SpringBoot Vue 的前后端分离在线考试系统。这个项目的核心价值非常直接——它提供了一套完整的、可直接运行的源码、数据库和项目文档&#xff0c;目标是让你在短时间内&#xff08;比如标题宣称的1小时&…

作者头像 李华