AI 为主题配置流程提效实践经验分享

李瑞东 发布于

背景

我们设计组建立并维护了一套设计系统,并且也有一个「主题编辑器」,支持可视化配置全局/组件维度的颜色、圆角和字号等。

虽然我不是主题编辑器项目的负责人,但我对这个平台是有些感情的,因为这是我刚来这家公司不久就深度参与的设计中台项目之一,当时加班加点梳理组件 Token 明细、逐个组件编排配置面板等场景还历历在目。

当时我们设定「主题编辑器」的使用路径是这样的:

  1. 要基于当前 React 组件库的框架进行主题/风格的定制时;
  2. 在主题编辑器里对全局样式或组件配置项进行编辑;
  3. 发布主题后,将主题包的哈希值交付给前端开发;
  4. 以后前端调用组件库时,应用的是经过设计师精调的风格。

这个主题编辑器最初的构想很美好:当不同业务的产品/设计对设计风格有自定义要求,但又不想重新设计开发一套组件库,就可以通过「主题编辑器」基于当前的 React 组件库来手动配置一套样式。

网上其他品牌的组件库也有类似工具,比如:Arco / Ant Design 的主题编辑器,其实和我们公司内部是一样的东西:

思考

我自己也帮业务系统配置过主题,当时感受到一个很痛的痛点:主题配置太麻烦了,必须逐条手动修改。

目前主题编辑器主要有两个使用场景:

  1. 设计师在 Figma 对系统的主要设计风格进行定义、出了几个主界面的设计后,在主题编辑器里对照设计稿逐条配置;
  2. 产品想参考某个系统/平台的风格,但是不会进行配置(或者觉得麻烦),最终还是找设计师来帮忙。

AI 时代来临之后,公司领导常说要研究如何让 AI 为旧流程提效,我觉得这里可能有机会点。

启发

我在网上看到过有些工具是在线提取指定网站的设计风格,能把主题色、边框色和字号梯度等等都抓取下来,并生成一份 DESIGN.md。

这个工具看上去很哇塞,但是却很难进入到 B 端工作流里,原因有二:

  1. 无法访问要登录的站点或内网 —— 比如发一个阿里云后台的链接,在这种平台上是无法访问的;
  2. 输出物无法直接被内部的主题编辑器消费 —— DESIGN.md 与主题编辑器的 Schema 毫无关联。

受此启发,我们设计师也可以做个浏览器插件:

提取任意网站的设计风格,并输出一份适用于内部主题编辑器的配置参数。

当时想做成浏览器插件而不是 SKILL 的主要原因有两点:

  1. 绕过登录态。SKILL 里做内网登录状态相对麻烦而且细碎,插件天然长在我浏览器里,登录态现成就有;
  2. 稳定采集页面样式。浏览器打开看到的是渲染后的样式,而且可以直观地指定想要采集的页面风格。

这是「主题风格提取器」插件的真实使用过程录屏。如果对实现过程有兴趣,可以继续往下看。

下面就来分享下这个插件的制作过程和细节。项目里会有些纠结和取舍,也有一些我与 AI 斗智斗勇的过程,对我来说是一段宝贵的经历。

方案规划

因为是探索型项目,在做之前我也先思考了下这个功能的能力边界:我需要做到什么程度,以及可以做到什么程度。

我们当前的主题编辑器里的配置项很多很细,细到 Checkbox 里图标和文字之间的距离、Tabs 高亮指示器的粗细等等都能进行配置。

而每个网页呈现的内容不同,样式的写法也不同,事无巨细地对所有样式参数进行抓取不现实。

所以我决定仅提取目标网站上小部分对整体风格有关键影响的样式,并在此基础上推算出全量的参数配置。前期我先按以下流程进行分析:

  1. 将当前主题编辑器里的样式配置项梳理一遍;
  2. 筛选出能较大程度影响视觉风格的那些配置项;
  3. 插件就专门提取这些配置项,基于一套给定的推导规则把全量样式参数推出来;
  4. 最后输出为可导入主题编辑器的 JSON 格式。

最终我筛选出以下关键配置项:

类型配置项名称
主题色brand-6
成功色success-6
警告色warning-6
危险色danger-6
中性色(文字)neutral-text-5
中性色(填充)neutral-fill-6
中性色(边框)neutral-border-1 ~ 2
页面背景色background-layout
默认字号font-14
默认圆角border-default

明确输出物后,接下来的任务也就明确了:

  1. Vibe Coding 把「采集 + 输出」的插件做出来,把功能跑通;
  2. 找多个网页进行采集生成,将生成的内容与真实网页效果对比测试准确度。

制作插件

插件功能开发是基本上没有难度,现在的 Code Agent 开发这种项目都很轻松。整体走这样的提取路径:

  1. 批量采集页面上的元素样式 (Computed Styles),比如背景色 background-color、字号 font-size、圆角大小 border-radius 等;
  2. 数据处理:
    1. 合并多页:插件支持采集多个页面,用脚本把多个页面里相同的色值、字号等合并统计数量;
    2. 聚合相同样式:以组件维度,把相同的样式合并为同一条;
    3. 裁剪数据:每个类目取最多 20 条不同的样式,防止信息过载;
  3. 把处理后的数据打包交给 AI,让 LLM 基于样式数据 + 提示词推理出完整样式表,以 JSON 格式输出。

功能跑通后,我迫不及待找几个网站测试效果,但结果令人咋舌。

最开始我以为这件事情很简单,但是现实是:生成内容准确率非常低。举几个例子:

  1. 以黑白相间(或灰白相间)模块来展示内容的网站,此时输出的结果很容易有误 —— 多种 background-color 出现频率一样时,取哪个?
  2. 网站明明是 12px 字体风格,输出结果却是 14px —— 非文字元素也会有 font-size 属性。

所以我对这个项目的理解是这样的:

采集样式和输出结果(无论是输出 JSON、DESIGN.md 还是 HTML)都不难,难的是结果的准确度。

每个样式类型都要设定更详细的规则,而这正是我这次项目花时间最多、同时收获也最多的地方。下面分享几个点,说说我是用了什么方法让输出结果更准确。

优化策略

重建颜色梯度

一套设计系统里,颜色、字号、圆角等样式 Token 都需要建立梯度,而这正是插件容易犯错的地方 —— 很难保证这些梯度里所有的参数都出现在被采集的页面上。

因为我这插件采集样式的来源是用户当前打开的页面,是基于渲染出来的前端页面来采集的。所以如果一些颜色梯度没有出现在页面上,采集器是无法感知到的。

我曾经试过扫描 CSS Variable 语义化变量名的方式,因为理想状态下,页面上所有用过的颜色都会取自于这个网站自身的颜色变量表。但我最终没有用这个方案,因为在 B 端后台的场景里,事情没有那么简单 —— 在一些历史包袱重的后台,一个系统有多份变量表的事情屡见不鲜。

最终我用了一个自己觉得比较靠谱的办法,虽然会损失一点精确度,但能确保输出物是完整、可用的。我做了一个「AI 定锚点色,算法重建梯度」的策略,具体如下:

  1. LLM 基于采集的数据确定锚点颜色,比如:系统主题色、一级文字色;
  2. 用颜色算法把完整色阶计算出来,其中:
    1. 主题色、有明显色彩倾向的颜色:用 Arco 开源的颜色推导算法;
    2. 中性色(填充、文字色):用自己捣鼓的灰度插值算法,基于我给定的步长。

这种做法可能会与目标网站的真实设计系统有些许偏差,但能大幅提升产出物的整体完整性、可信度和可解释性,并且有效避免采集错误导致色阶跳跃、步长分布不均匀等问题。

值得一提的是,无论是彩色还是中性色的色板推理,都要区分浅色/深色主题。在深色模式下,彩色色板的饱和度会稍微降低,明度稍微提亮;而中性色普遍调高明度,与浅色主题的的色板相反。

正好 Arco 的颜色生成算法会区分浅色/深色主题:同一个基准色值在两种主题下生成出来的颜色梯度会完全不同。所以插件也会识别当前站点的主题模式。

优先用脚本抓取当前网页的 CSS 属性 color-scheme,如果没有,则让 LLM 发挥它的特长。LLM 侧的方案如下:

  1. 采集阶段:在插件面板点击「采集」时,自动把当前网页截图下来;
  2. 预处理:对图片做轻微的质量压缩和分辨率控制(节省 Token);
  3. 生成阶段:用户点击「生成」时会将图片发送给 AI,先让其给出一个确定的回答:这个网站是浅色(或深色)主题;
  4. 基于 AI 给出的回答,调用颜色算法的不同功能。

按语义分类数据桶

边框色

我们的主题编辑器里定义了两种边框色:border-1 和 border-2。从语义角度,分别对应的是「默认分割线颜色」和「可交互控件的边框色」。

按我们集团的设计系统,交互控件的边框色都会比分割线颜色深,所以最开始的取值逻辑就是取出现频率最大的两个描边色,然后根据明度排序来定义 border-1 和 border-2。

测试后发现这个方式太不靠谱了,简单举个例子:一个网站页面(尤其是功能复杂的 B 端后台界面)里有可能出现 >2 种描边色,如果刚好采集的页面可交互控件比较少,就会被排到第三位,最终输出错误的边框色。或者一个平台里的边框色基本统一,这个方法就会给出明显的错误结果。

所以对于边框色,我按照语义对数据进行分类,设定一个叫「可交互控件」的桶。具体做法如下:

  1. 定义「可交互元素」:通过标签名 + Class 关键词 + role 属性等方式进行定义;
  2. 让 border-1 取「非可交互元素」里出现频次最多的边框色;
  3. 让 border-2 取「可交互元素」里出现频次最多的边框色。同时:
    1. 排除饱和度 > 12 的颜色(防止有主题色的 Ghost 按钮干扰);
    2. 没有采集到时用 border-1 颜色作为兜底。

注:在第一步如果仅取 <button>、<input> 是不准的,因为按钮有可能是一个 <span> 改造而成,或者输入框的 CSS 样式包在上层 <div> 里。

分别在两个桶内采集数据,实测让输出准确率提升了很多。

圆角兼容处理

由于我们同样不可能准确提取到某个网站的所有控件的圆角大小,所以我们可以利用刚刚定义的「可交互元素」桶。

通过仅提取「可交互元素」的圆角尺寸,以这个尺寸作为锚点来推测出这个系统的圆角风格,并扩展到其他组件上。

下面具体分享下不同的默认圆角大小下我会怎么处理:

  1. 如果圆角处于正常范围,比如 2px、6px 或 12px。我可以将绝大部分组件的圆角(标签等小型组件除外)都统一调到提取出来的默认圆角大小,确保整体风格一致;
  2. 如果是全圆角风格,比如采集到的参数是 1000px、9999px 或 50%。这时候就不能将提取出来的值应用到所有组件上了。因为在块状组件(比如多行文本框、穿梭框、折叠面板等)用这种超大的圆角会出现样式异常。

所以我也做了个特殊处理逻辑,针对「全圆角风格」的情况:

  1. 在中小型组件里保持使用这种全圆角样式,此时会呈现胶囊形状;
  2. 在块状组件里取一个主题编辑器定义的非全圆角上限:24px,此时会呈现大圆角样式,符合整体风格。

按语义降噪

对于页面背景色,最开始插件用的是很简单的逻辑:统计网页里 background-color 的色值,取出现频率最高的。

但是这种方式正确率很低,举个例子:一个后台管理页面里,只有页面背景设为了灰色;但输入框、按钮、侧边栏等这些能盖在背景上层的元素,背景色都是纯白色。此时 AI 很容易推断出页面整体背景色就是白色。

当时基于 AI 的建议,调整了取色逻辑,取 body 或者 [id="app"] 的背景色,或者取网页 CSS 变量表里带有 bg 或 background 的颜色 Token。

但很快就被验证不靠谱了:有些后台的 body 和真实背景色不匹配,或者没有设置色值。变量表的方法同样有盲区,出现多个带有 background 关键词的变量名时,AI 未必能把正确的选出来 —— 甚至如果 body 和 --background 的颜色不同,此时又取哪个?全交给 AI,随机性太大了。

为了提高准确性,我还是用基于「背景色」的语义排除噪音的做法,具体如下:

  1. 排除面积小于视窗 35% 的元素:避免把输入框、卡片等背景色纳入;
  2. 排除干扰元素:比如 nav、aside、footer、img、path 等存在背景色属性但明显与页面背景色无关的元素;
  3. 排除绝对定位元素:fixed、absolute。

去掉噪音后,我取了前 5 个面积最大的背景色,并且把其他比较贴合「背景色」语义的参数也一并打包进数据集里面,希望能帮助 LLM 更好地判断。

具体打包了元素的面积和 DOM 层级深度 —— 因为承载背景色的元素大概率面积会很大,而且层级深度相对浅。同时把当前页面的主题色(前文提到用 AI 视觉识别的结果)也打包进去。

此时再让 AI 推理出背景色,实测输出结果的准确度上了好几个档次。

收获

这个工具最终效果蛮不错的,前面表格里列出来的关键颜色都能准确提取出来。配合一套推算规则把全量样式参数都推出来之后,导进主题编辑器内就能快速配出一套与某站点风格高度相似的主题,省下了很多时间。

这个项目最有意思的过程是通过不断尝试,在具有不确定性的 LLM和能稳定 I/O 的脚本中找到一个能同时利用两者优点的策略,输出符合预期的结果。

整个项目耗时不到一周,前期快速搭好功能之后,就得耐心地逐个调整采集策略,不断找各种网页进行测试、改规则等等。

而且我发现 Vibe Coding 流程里有一点很累的是:组织语言。 得在对话框里组织好语言,把相关的上下文理清楚,重点关注什么,让 Agent 别往哪个方向思考等等,才能获得一个比较好的结果。

Context is everything.

🎉 你觉得这篇文章怎样?
我在这里留下了联系方式。如果觉得这篇文章还不错,欢迎分享给朋友!
联系作者
复制链接
© 李瑞东 2017-2026