落地页设计师(提案轮次)
以轮次方式提案落地页的方法、每项决策的基础,以及页面在任何人看到之前必须通过的检查。此技能的上游:website-concept-architect(站点定义)。下游:ui-ux-architect(移植到应用中)。
0. 任务及其范围
- 绘制,而非重构。 输出位于
<proposals-dir>/<date>/<product>/下。不要触碰应用的发布代码;除非所有者要求,否则不要提交或推送。 - 只有当页面通过验证栏(第8节)并且其声明可追溯(第2节)时,才算完成。
- 按轮次工作。每轮产生新的方向,保留旧方向作为创意库,并以推荐方案及其胜出原因结束。
1. 标准(“令人印象深刻”的含义)
对照此列表评判每个截图。
- 五秒钟。 仅凭第一个视口,陌生人就能说出产品做什么、为谁而做以及有何不同。
- 一个设备。 页面因一个特定、产品独有的东西而被记住,而非颜色。好的设备是具体的:标志中的光标用作真实光标;一个移动的真实数字;一个代理到服务器的交换,显示为它真实的两次调用;一个推送在副本所说的同一时刻到达手机。
- 具体,而非抽象。 每个声明都指向产品或代码中的具体内容。
- 真实像素胜过插图。 运行中产品的裁剪截图胜过任何对其的绘制。
- 说明权衡。 文案说明它做什么、为谁而做,以及它接受什么作为交换(自托管:你的更新和备份;一个共享服务:又一个依赖;仅交付:策略保留在应用中)。
- 禁止: 库存照片、紫色渐变、带图标灰色卡片的便当网格、“受到 10,000 个团队信赖”、虚构的推荐、虚假指标。
2. 研究先行:带来源的事实
在绘制之前,为每个产品构建一个事实表:声明、值、源文件。阅读代码,而非营销资料。
- 查看位置:
README.md、AGENTS.md/CLAUDE.md、设计文档和 ADR、CHANGELOG.md、验证器和错误代码、工具/端点注册、线/proto 映射、worker/重试常量、品牌标记组件、主题令牌文件、现有落地视图。 - 值得查找的事实: 精确的工具名称及其破坏性数量;错误代码和消息;常量(重试次数、退避基数和上限、轮询间隔、信任限制);请求字段(在线映射中计数,而不是文档中);路由;真正的快速启动命令。
- 在代码中验证计数和名称。 文档会漂移:文档中记录的“六个字段”在代码中可能是八个;README 可能指向一个不再存在的目录;英雄示例可能使用服务器拒绝的单位。
- 标记问题,切勿静默修复。 不一致之处(截图中的过时品牌、相互矛盾的截图、文档与代码)写入
NOTES.md,如果相关,也写入页面。 - 在页面上标注说明性数据(示例条目、ID、时间、通知文本)。读者必须无需注释即可区分真实数据和样本。
3. 品牌与家族
- 每个产品保留自己的标记和强调色。 从其组件复制真实的标记路径,从令牌文件复制真实的令牌(背景、文本、柔和、强调、强调文本、语义颜色),两个主题都要。
- 字体:仅产品自有的,复制为 woff2 放入
fonts/。在选择字体风格前进行检查:在其完整重量范围内声明的可变字体,可以为一个产品提供发丝般的数字,为另一个产品提供动态的黑体重量,而无需新字体。python -c "from fontTools.ttLib import TTFont; t=TTFont('inter-latin.woff2'); print([(a.axisTag,a.minValue,a.maxValue) for a in t['fvar'].axes])" - 组织品牌套件是家族,而非模板。 将其用于小的共享细节(一个引出标记,一个
currentColor的页脚致谢),切勿用作产品的身份。 - 家族层: 一个共享文件,包含间距、类型和运动令牌、页眉、按钮、引出标记、章节导轨、电影控制、复制按钮、页脚和运动套件。产品覆盖颜色、字体风格和构图。多个页面应如同具有不同个性的兄弟姐妹。
4. 每个产品的艺术指导
在布局之前确定一个个性;让它驱动字体、网格、颜色强度和节奏。先前成功的示例:
| 个性 | 字体风格 | 构图与节奏 |
|---|---|---|
| 平静、编辑型(金融) | 一个巨大的英雄图形,使用较轻的重量和表格数字;记账行使用等宽字体 | 宽敞的空白、不对称网格、一个夜间带、一个满版真实截图 |
| 响亮、动态(健身) | 黑色重量、紧密的负字距、超大数字 | 带滚动条计的满版强调带、硬规则、交替的响亮和安静部分 |
| 技术、精确(身份) | 等宽标注、大等宽数字 | 发丝网格地面、带标题的编号图形、带注释的图表 |
| 简洁、有节奏(通知) | 巨大的等宽状态词 | 作为重复主题的时间标尺、负空间、一个固定部分 |
- 避免默认骨架(眉毛、h1、引导、两个按钮、信任列表、发光),除非你有意改变它。一轮中所有产品共享一个骨架即失败。
- 像电影一样安排长页面的节奏:一个安静部分、一个响亮部分、一个满版瞬间、一个暗带、背景变化。均匀的间距读起来像拼接。
- 有意设计 390 像素:为手机自行裁剪截图、重新流动的图表(堆叠、侧总线)而非缩小、折叠上方的电影内容。
- 联系表检查: 并排渲染所有产品的第一个视口(两个主题,1440 和 390)。寻找相同性和家族断裂。
5. 英雄电影
每个产品一个编排好的序列,在 4 到 8 秒内讲述产品,并定格在静态最终状态。
- 最终状态是纯 HTML。 关闭 JS 和减少动画时立即显示;电影只动画到最终状态(一个用于起始状态的
reset(),步骤[ms, fn(instant)],end()清理)。 - 在视图中播放一次,从不循环;标签页隐藏时暂停;有一个可见的暂停/重播控件(WCAG 2.2.2)。电影内的打字由电影时间线驱动,因此暂停也会冻结它。
- 按序列讲述真相。 使用真实行为作为情节:请求 → 被真实错误拒绝 → 重新发送 → 保存;三份 → 一份;排队 → 轮询 → 发送。不要伪造数据不支持的高亮。
- 共享元素移动(一个总数飞入英雄图形,表格飞入一个数据库)形成一个场景,而不是一系列揭示。
- 无障碍文本:可见的打字层是
aria-hidden;完整句子一旦进入.sr范围。
6. 运动规则
- 门控: 内容默认可见;仅在
prefers-reduced-motion允许时,一个头部脚本添加html.anim;每个隐藏或动画规则都位于.anim下。 - 一次性揭示中仅使用不透明度(IntersectionObserver,结束于 1)。滚动相关效果(
animation-timeline: view()/scroll(),粘性擦洗)仅对变换、裁剪路径或描边进行动画处理:半透明文本状态在 axe 中无法通过对比度。 - 允许:具有静态回退的 CSS 滚动驱动动画、主题切换的视图过渡(从切换开关出发的圆形擦除)、CSS
linear()弹簧、可变重量动画、在运动关闭时写入最终文本的计数动画。 - 自动移动的内容(滚动条计、自动播放)需要暂停控件,并在悬停/聚焦时暂停。
- 测量布局偏移;为计数器和打字文本预留空间。
7. 截图
- 仅来自运行中的产品,绝不来自其模型。确定性地种子演示数据,以便数字在截图中一致(或在页面上说明它们不一致)。
- 有意裁剪(每个点一个面板),两个主题,2 倍,加上单独的手机裁剪。
- 裁剪掉过时的品牌并标记。当 UI 语言与页面不同时,在标题中说明。
- 实现为具有
height:auto、有意义的alt以及位于截图坐标空间(测量它;标记会漂移)中的标记的浅/深<img>对。 - 如果构建被阻塞(私有包、缺少令牌),说明情况,将绘制数据标记为说明性,并列出确切的解除阻塞方法。
8. 硬性需求和验证栏
每个页面:
- 自包含的 HTML,内联 CSS 和 SVG,无 CDN,仅产品字体;200 KB 以下(不包括截图)。
- 通过
data-theme实现浅色和深色,带切换开关(存储偏好,系统默认)。 - 地标,一个
h1,无间隙的标题顺序,跳过链接,焦点可见,44 像素目标,强制颜色回退。
检查(在向任何人展示之前,所有必须通过):
verify.js: axe-core(wcag2a/2aa/21aa/22aa + 最佳实践)在 390x844 和 1440x800 × 浅深 × 运动减少 = 8 次运行,零违规。在运动模式下先滚动整个页面,以便揭示触发。此外:无水平滚动;图片被阻止时仍可读;JS 关闭时仍可读。- HTML 解析器检查 吞咽文本:原始
<token>或<no-reply@…>在文本中成为标签,axe 不会告诉你。转义为<。 - 每个页面的冒烟测试:在 1440 和 390 处点击每个控件,在
pageerror上失败,在交互结束状态(对话框打开,应用后)再次运行 axe。 - 截图: 动画结算和减少动画,两个主题,两个宽度。查看它们并至少作为严厉的艺术指导迭代两次。
- 说明未涵盖的内容: 屏幕阅读器、Safari/Firefox、真实设备、五秒声明的用户测试。
9. 陷阱(每个都曾花费时间)
- CSS 特异性:主题切换的图像规则必须击败组件规则(
img.sl,而非.crop img)。 - 测量隐藏元素返回 0(镜头、缩放):显示,然后测量。
- 不透明度降低的非活动步骤无法通过对比度:改用边框/背景强调。
role="list"需要listitem子元素;章节标题不得从h1跳到h3。- 发光/网状背景需要满版、遮罩和
body{overflow-x:clip}。 - 网格单元格中的不可断开的
<code>会在 390 处导致水平滚动;可滚动的pre无法通过scrollable-region-focusable(赋予tabindex="0"、role="region"和唯一标签,或使用pre-wrap)。 - 通用类名在共享和产品 CSS 中冲突(
.tl、.copy):为家族类命名空间。 cqw针对祖先容器解析,而非元素本身。- 与可见文本不同的
aria-label会破坏标签内的名称;将额外上下文放在.sr范围中。 - 缺少
f前缀的 Python 模板字符串会将{label}泄漏到可访问名称中:grep 输出。 loading="lazy"图像在整页截图中缺失;非缺陷。- 通过提取组装的页面在源更改时不会更新,直到重新运行组装器。
10. 流程
- 阅读 简报/交接、产品代码和文档;构建事实表和标记(第 2 节)。
- 盘点品牌: 标记路径、令牌、字体(轴)、现有截图及其问题。
- 方向轮次: 每个产品 3 个小的、不同的方向,每个围绕一个设备构建。保留它们作为创意库。
- 所有者反馈 → 将最佳想法组合成一个长页面(章节导轨、常见问题、带复制按钮的真实快速启动、一个加权的“你接受什么”块)。
- 提高上限: 首先构建一个共享的家族层,然后为每个产品构建一个带英雄电影的艺术指导页面。独立产品可以并行构建(每个产品一个代理,家族层只读,建议报告并在一次应用后返回,然后所有页面重建并重新验证)。
- 一起审查: 联系表、家族层中的一致性修复、完全重新验证。
- 交付: 每个产品一个
NOTES.md(概念、真实与样本、标记、验证表);一个用于下一会话的HANDOFF.md(目标、决策、标记、弱点、下一步想法);仅查看的独立预览(内联字体和截图);一个包含每个产品的推荐及其胜出原因的简短摘要。
11. 文件和工具
<proposals-dir>/<date>/
HANDOFF.md 下一会话的简报
<product>/direction-N.html 页面;NOTES.md;fonts/;shots/
_tools/verify.js axe x8,溢出,图片被阻止,JS 关闭
_tools/family.py 共享外壳、令牌、运动套件(电影、计数、类型、onView)
_tools/build_<product>.py 每个产品一个生成器
_tools/settled.js 电影结算后的截图
_tools/standalone.py 仅查看副本,内联字体和截图
_tools/smoke_<product>.js 交互冒烟测试
生成器携带创建它们的会话中的硬编码路径;在运行前修复 sys.path 和输出路径。verify.js 期望在兄弟目录 verify/node_modules 中安装 [email protected]。
12. 展示页面前的检查清单
- 第一个视口通过五秒测试;一个设备在那里可见。
- 每个数字和名称都追溯到文件;样本数据在页面上标注;标记在
NOTES.md中。 - 权衡被直白陈述并赋予视觉权重。
- 英雄电影结算;最终状态为默认 HTML;暂停/重播有效;减少动画和 JS 关闭时阅读良好。
- 滚动相关效果仅使用变换/裁剪/描边;揭示为一次性。
- 设计了 390 像素(自行裁剪、重新流动图表),而不仅仅是堆叠。
- verify.js 完全通过(8 次运行),解析器检查通过,冒烟测试通过,小于 200 KB。
- 查看了截图,两个主题,两个宽度,并根据所见更改了某些内容。