Web UI 工艺
通用 UI 不是一种风格。它只是任何没有人做出的决定的填充物:模型、模板或框架提供了最常见的答案,结果可能属于任何产品。最好看的网站(Linear、Vercel、Stripe、Family、Awwwards 获奖者)几乎不留下任何默认设置。它们计算一个小型系统,致力于一个想法,并将功能细节保持在可衡量的标准之下。
因此,任务就是做出决定,将它们写下来,并将每个决定追溯到主题、用户或感知的物理原理。按顺序执行以下五个步骤。根据任务规模进行调整:单个按钮只需一句简报和快速审查,而落地页则需要完整的处理。
1. 理解主题
在任何视觉选择之前,先确立:
- 主题:产品、组织或内容实际上是什么,以及它所属的世界(其行业、材料、词汇、手工艺品)。
- 受众:谁会来,他们已经知道什么,他们可能使用什么设备。
- 首要任务:页面或屏幕必须完成的一件事。其他一切都服从于此。
- 现有约束:品牌资产、现有的设计系统、令牌、组件库或仓库中的框架。如果存在令牌,请使用它们并在此技能范围内应用它们。除非要求,否则不要将新的身份强加于已建立的产品。
如果用户提供的信息很少,则从主题推断,并在简报中陈述你的假设,而不是提出一堆问题。
2. 编写设计简报
在编写代码之前,在你的回复中编写一份紧凑的简报。它就是设计,因此必须足够具体,以至于其他人可以从中构建出相同的东西。
方向: 一个命名的美学风格以及它为什么适合这个主题(一两行)
签名: 这个页面因之而被记住的一个想法,承载它的核心元素,以及这个元素将如何制作
(提供的资源、生成的图像,或通过代码构建)
调色板: 中性色(向...倾斜)、一个强调色(角色)、语义颜色;使用 OKLCH 值
排版: 为每种字体(展示、正文、如果需要则用等宽字体)确定字族和角色,以及每种字体与
主题的关联;展示字体在构图中的作用;比例尺;正文字体大小
布局: 首屏的两到三个选项,每个选项一行概念和一个 ASCII 线框图;
选择的方案及其原因;网格、行长、密度、区块节奏
深度: 表面如何分离(色调步进、细线边框、阴影)、光从哪里来、照在什么上面
动效: 层级(产品级或品牌级)、签名时刻及其主导元素、还有什么会动、动多久、
以及故意不动的部分
图像: 摄影、插画、3D、产品 UI 或纯文字;一行概括的美术指导
文案: 为受众编写的标题和主要行动;行动的命名,从按钮到确认保持一致
预算: 整个页面的压缩脚本大小以及特效层可以占用的份额
(默认为总大小 365 KiB;无特效页面为 75 KiB)
简报的规则:
- 推导,而非装饰。 每一行都要回答“为什么是这个,针对这个主题?”。从产品的材质中提取的调色板,从其语言中提取的字体,以世界上最具特色的东西作为开场的主角。
- 一个签名,其他保持安静。 Stripe 有它的渐变波,Apple 有它的滚动擦洗产品照片,Family 有它的飞行托盘。大胆只用一次。围绕它的克制才能使签名被阅读。
- 克制是有效的方向。 一个安静、以文字为主导、单色、带有一个强调色的系统,与一个 WebGL 主角一样是深思熟虑的选择,并且通常是工具和文档的正确选择。
- 安静不是空白。 克制限制了页面有多少想法,而不是每个想法有多丰富。签名应该值得长时间审视:为这个主题绘制的插图、仔细布置的真实数据、纹理、真正展示比例的文字。食品、文化、消费和品牌主题通常需要图像或插画来传达温暖,所以针对这些主题的纯文字页面需要说明理由。
- 主角是投入精力的地方。 广受赞誉的网站打破了许多规则,但仍然看起来昂贵,因为有一个部件是按照非常高的标准制作的:带有可信数据的产品屏幕、打光的物体、原创的插图。选择它并使用
references/artefacts.md构建它。一个带有灰色条块的圆角框不是产品截图。 - 排版是构图的一部分,而不是它的载体。 在展示尺寸下,设置本身就是设计:相对于页面上最小文字的比例、粗细、宽度、大小写、换行位置、标题位于什么之上。Linear 的 64 像素标题配 12 像素界面文字是其效果的重要组成部分。
- 在选择一个布局之前先比较它们。 勾画两到三个真正不同的首屏(不是把图像移来移去的同一个布局),并根据主题的首要任务进行选择。脑海中浮现的第一个布局通常是模板。
- 声明、证明、行动。 大多数页面需要一个清晰的声明、一个真实的证据(产品视图、实时数字、客户、演示)和一个主要行动。结构遵循内容,而不是模板。
- 每个行动一个名称。 显示“发布”的按钮产生的确认是“已发布”,而不是“已保存”。界面的词汇是用户导航的方式。
在选择方向或签名时阅读 references/exemplars.md,在设置调色板、排版、布局和深度时阅读 references/visual-system.md,在编写动效行时阅读 references/interaction.md 的动效部分。
3. 挑战简报
在构建之前,先攻击它:
- 替换测试。 替换一个竞争对手的名字,是否还能让人注意不到?如果是,说明简报还没有做出决定。
- 每个选择测试。 对于每一行,问它是否可以属于任何产品。如果可以,它必须是来自下面构建表的、刻意且调整良好的默认值,或者必须改变。
- 收敛测试。 用几行草稿写出你会为相邻主题(同一类别中的另一个工具、同一行业中的另一个制造商)编写的简报。每一行相同的输出都是一个默认值,而不是一个决定。改变它,并在简报中说明改变了什么以及为什么。只有当一行出自两个主题共享的一个事实(两个产品都是硬件,两个受众都阅读代码)时,才可以保留;说出这个事实的名称。
- Tell 检查。 对照
references/slop-tells.md进行检查,包括整体外观集群。不要用一个默认值替换下一个最常见的一个(用 Space Grotesk 替换 Inter,用紫色替换蓝绿色)。用一个有理由的选择来替换它。
修改简报,然后构建。
4. 构建
- 先定义令牌。 在任何组件之前,将调色板、字号比例、间距、圆角、阴影和动效作为 CSS 自定义属性(或项目的令牌系统)编写。组件仅使用令牌名称,永远不要使用像
bg-indigo-500或#6366f1这样的原始值。 - 其次处理结构。 语义化 HTML,导航使用真实链接,标题按顺序排列,然后是样式。
- 应用下面的构建表以及
references/visual-system.md和references/interaction.md中的细节。 - 设计每一种状态。 悬停、激活、焦点可见、禁用、加载、空、错误、成功、长内容和短内容。生成的 UI 在这里最薄弱,而修复在这里最便宜。
- 保持特效廉价且可选。 重特效(WebGL、视频、大模糊)位于简报预算内的一个独立层中,在首次绘制后开始,有静态回退,并位于
prefers-reduced-motion: no-preference之后。
5. 批判和删减
将第一个构建视为草稿。
-
运行静态检查器,使用技能自己的目录作为脚本路径。它需要 Python 3.12 或更高版本,并且不需要任何包。将其指向整个前端源代码,而不仅仅是你更改的文件:焦点和减少动效规则会扫描全局样式,部分扫描会报告错误的缺陷。
python <skill-dir>/scripts/check_slop.py <前端源代码文件夹>修复每一个
defect(退出码 1 表示至少还有一个)。对于每一个tell,要么更改它,要么在你的报告中说明为什么保留它。检查器只读取源代码文本,因此干净的结果是必要但不充分的。 -
渲染页面,并在 1440px 和 375px 宽度下查看,如果有两种配色方案则都查看。如果会话中有浏览器工具,请使用它。否则,大多数机器都有 headless Chrome 或 Edge;将截图和浏览器配置文件写入临时文件夹,然后读取图像:
chrome --headless=new --hide-scrollbars --user-data-dir=<temp>/profile --window-size=1440,2600 --virtual-time-budget=4000 --screenshot=<temp>/desktop.png <文件或 http URL>截图是给定大小的一个视口,而不是整个页面,因此要使窗口足够高以容纳你需要查看的内容。Headless Chrome 不会使窗口宽度小于大约 500px,因此 390px 的截图会从更宽的布局中无声地裁剪出来。自我播放的元素会在其循环的随机点被捕获:为最终帧添加
--force-prefers-reduced-motion,并另外截图一张不带该标志的以查看循环中间帧。对于手机检查,截图一个包含宽度为 375px 的<iframe>中容纳网站的包装页面。通过滚动显示的元素可能不会出现在 headless 截图中;请在源代码中检查其隐藏的初始状态是否由脚本应用(参见references/interaction.md)。如果使用真实的浏览器工具,还要 Tab 浏览每个流程。 -
测量页面而不是估计。通过 HTTP 提供服务(对于静态文件夹,在该文件夹中运行
python -m http.server),在其默认移动配置文件下运行 Lighthouse,然后使用预算读取器读取报告:npx [email protected] <http URL> --output=json --output-path=<temp>/report.json --quiet --chrome-flags="--headless=new --user-data-dir=<temp>/lh-profile" python <skill-dir>/scripts/check_budgets.py <temp>/report.json --script-kib <简报中的预算>它检查 LCP(2.5 秒)、CLS(0.1)、总阻塞时间(200 毫秒,实验室中的 INP 替代指标)、脚本大小与简报的匹配情况,并列出每个非合成动画的元素。修复每一个
breach(退出码 1)。退出码 2 表示某个指标unmeasured或报告不可用:重新运行,如果仍然失败,则报告该指标为未测量,绝不报告为通过。http.server不压缩,因此脚本大小读数偏高,这出于安全考虑是好的。如果 Lighthouse 找不到 Chrome,请设置CHROME_PATH。如果 Node 或网络不可用,请在报告中说明。Lighthouse 不测量签名时刻的帧率:如果会话中有浏览器工具,则记录性能跟踪,否则说明它未测量。 -
询问首屏是否提供了值得一看的东西,并对核心元素运行
references/artefacts.md中的保真度检查清单。一个正确但令人难忘的页面有一个胆怯的签名:加强签名,而不是添加更多元素。 -
将页面与参考进行对比。在所选方向中选择一个广受赞誉的网站,一个该领域的设计师会欣赏的网站(
references/exemplars.md列出了一些),使用第 2 项中的命令在 1440px 下截图其首屏,然后将两张图像并排放置。比较核心元素的保真度、最大字体与最小细节之间的跨度、有多少可信的细节,以及光线。说出最大的差距并缩小它,或者在报告中说明为什么保留它。参考设定了工艺的标准,而不是外观:不要从其表面借用任何东西。如果网站无法访问,请在报告中说明。 -
执行
references/interaction.md中的检查清单(状态、焦点、目标、表单、性能)。 -
针对构建的页面(而非简报)重新运行
references/slop-tells.md中的 tell 检查。它涵盖了检查器无法看到的结构性 tell,例如居中的徽章英雄、三个相同的卡片和整体外观集群。 -
删除任何不为主题或用户服务的东西:装饰性分隔线、自解释内容上方的标签、徽章、发光、重复文本的图标、第二个强调色。删除通常是可用的最大改进。
-
报告简报、批判改变的内容、与参考的最大差距、针对预算的测量数据,以及你无法验证的任何内容(例如,没有浏览器时的渲染对比度)。
构建表
来源充分的开端值。它们保护好的决策;它们不取代简报中的身份决策。
| 维度 | 默认值 |
|---|---|
| 正文文本 | 16 到 20 px,行高约 1.5,行长 45 到 90 个字符(目标约 65) |
| 标题 | 行高 1.0 到 1.2,24 px 起字间距约 -0.02em,text-wrap: balance |
| 段落 | text-wrap: pretty;粗体和斜体永不同时使用 |
| 字号比例 | 使用 clamp() 实现流式缩放,小屏幕比例约 1.2,大屏幕约 1.25 |
| 全大写 | 很少使用,不超过一行,字母间距 0.05em 到 0.12em |
| 色彩 | OKLCH;一个带色调的中性色阶,一个强调色,三到四个语义颜色,每个都有基于角色的阶梯 |
| 对比度 | WCAG 4.5:1 正文,3:1 大文本和 UI 部件;正文文本目标 APCA Lc 75 或更高 |
| 深色模式 | 一个单独的调色板:深灰色基底(约 oklch(0.18 0.01 h)),较亮的表面表示层级,降低饱和度的强调色 |
| 渐变 | 使用 in oklch 插值;相邻色相;可选精细渐变;最多一个刻意的渐变 |
| 间距 | 以 4 px 为基数的系统:4, 8, 12, 16, 24, 32, 48, 64, 96, 128;组间距至少是组内间距的两倍 |
| 深度 | 首先使用色调步进和细线边框;阴影分层,一个光源,用表面色相着色 |
| 圆角 | 两到三个值;嵌套圆角 = 外层圆角减去内边距 |
| 图标 | 一个字族,一个网格,一个笔画宽度 |
…
[内容已截断以用于翻译]