Communitygithub.com

排版规则 (hr-better-typography)

Web UI排版规则:字号比例、行高、换行、截断、表格数字、字体加载及移动端输入框文本大小。适用于样式化或审查Web UI CSS中的文本渲染效果。

排版规则 (hr-better-typography) 是什么?

该技能为Web UI排版提供了一套全面且细致的规则,涵盖从字体加载、字号比例、行高、字间距到文本换行、截断、表格数字等各个环节。其核心原则是审慎使用排版工具,为不同角色(如标签、表格单元格、标题、正文段落)设定不同的规则。技能强调使用CSS属性而非原始标签,并建议使用语义化的字号名称。对于文本截断,提供了单行(`text-overflow: ellipsis`)和多行(`line-clamp`)的方法,并在截断时需考虑内容的可恢复性。特别地,技能解决了iOS Safari中移动端输入框小于16px时页面缩放的问题,并给出了两种解决方案。此外,还包括了对字体合成(synthesis)、字重与尺寸的配合、测量(measure)、对齐、下划线样式及文本可选性(`user-select`)的指导。技能适用于Claude Code、Cursor等AI代码编辑器及AI Agent平台,通过审查渲染后的页面而非代码来发现真实问题,并以结构化表格报告问题严重性和发现。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/bompus/house-rules/tree/HEAD/skills/hr-better-typography

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

排版规则

排版的要义在于克制:合理的比例、舒适的间距、足够的对比度。标签、表格单元格、营销标题和文章段落并不共享同一套规则。

审查时,请阅读渲染后的页面,而不是扫描代码。坏换行、孤行和截断问题只有在真实内容长度下才会显现。

所有修复请使用项目的样式系统,并采用下面给出的精确值,而不是看起来相似的等价写法。速查表将每个声明映射为其 Tailwind 等效写法。

文字内容本身属于 hr-better-writing。语义化的标题结构属于 hr-better-accessibility。空间上的 RTL 布局和逻辑属性属于 hr-better-layout。对比度测量属于 hr-better-colors。本技能负责文本在混合方向内容中的渲染、换行和行为。

提供正确的格式

在 Web 上使用 .woff2 格式,以获得 Brotli 压缩和广泛支持。.woff 是为非常老的浏览器提供的回退方案。.ttf 和 .otf 是桌面端格式,没有 Web 压缩能力。文件如何加载是项目本身关心的事。

使用属性,而非原始标签

当 CSS 属性存在时,就使用它。使用 font-weight: 650 而不是 font-variation-settings: "wght" 650。使用 font-optical-sizing: auto 而不是 "opsz"。使用 font-variant-numeric: tabular-nums 而不是 font-feature-settings: "tnum" 1。

属性在非可变字体回退渲染时仍能正常工作。仅对没有对应属性的自定义轴(如 "GRAD" 80)和特殊特性(如 "ss01" 1)保留原始标签。轴和特性标签列表详见 variable-fonts-and-opentype.md。

加载所需的字重和风格

浏览器会合成活动字体族未提供的字重或风格,从而扭曲真实字形。请加载设计所使用的那些字面。

font-synthesis: none 虽然可以关闭合成功能,但这样会消除强调效果,而并非报告它。只有在确认回退字体栈中的每个加粗、斜体、小型大写、上标和下标形式都能保持清晰可见后,再设置它。

更少的字体、字号和字重

很少使用超过三种字体。字重和字号定义了层次结构;过度使用它们会迅速损害可读性。配对时追求对比,而非相似:衬线标题搭配无衬线正文看起来是有意为之,而两个几乎相同的无衬线字体则显得像是个错误。

在 18px 以下,请使用 400 或更重的字重。低于 300 的字重仅在 28px 及以上的显示场景中使用;它们在正文大小下会消失。配对指南详见 choosing-fonts.md。

使用语义化的字号比例

定义一小套字号大小,并尽可能不偏离它。背后没有体系的硬编码字号在规模扩大时会崩溃。请使用 lint 规则或防护测试来强制执行此比例,该测试会在遇到任意非标准字号时失败。

当使用规则清晰时,像 text-sm 这样的独立默认名称是可以的。在团队中,请按用途命名字号(如 text-body-sm),以便规则能在他人的使用中存活。比例构建详见 spacing-and-sizing.md。

标题大小随级别递减

将标题级别映射到字号比例的递减步骤,使得视觉上次级的标题永远不会压制其父级。相邻级别在比例的小端可能共享一个字号,只要字重或间距能保持它们的区分。语义元素是 hr-better-accessibility 的职责;本技能仅设置视觉处理。

按角色设置行高

标题行高更紧凑,大约 1.1。正文行高 1.5 到 1.6。优先使用无单位值,以便行高随字号缩放;固定的 24px 做不到这一点。

紧凑的行高适用于短文本。任何包裹到三行或更多行的文本至少需要 1.4,即使在高度受限的行中也是如此。

按字号设置字间距

大标题通常看起来略微负的字间距更好看。小写的大写标签需要一点正的字母间距,否则字母会显得拥挤。阅读大小的正文不需要字间距。

限制行长

过长的行会让眼睛难以找到下一行。将长篇文本的行长限制在大约每行 60–75 个字符。任何单位都可以,只要存在一个限制并且行长落在这个范围内。详情参见 单位选择和像素等价写法。

有意地换行

四个声明,四个职责:

  • text-wrap: balance 在行间均匀分配文本。用于标题。
  • text-wrap: pretty 阻止一个短单词落在最后一行。用于描述。
  • overflow-wrap: break-word 用于长单词、链接或 ID 可能逃离容器的地方。
  • white-space: nowrap 用于标签和徽章,换行会显得破碎的地方。

在长篇文本中跳过 balance 和 pretty。

在变化的值上使用表格数字

默认情况下数字具有不同的宽度,因此计时器、计数器和价格会在更新时移动布局。对任何会变化的值应用 font-variant-numeric: tabular-nums。

截断但不丢失内容

对于单行,使用 text-overflow: ellipsis 配合 overflow: hidden 和 white-space: nowrap。对于多行,使用 line-clamp。截断会隐藏内容。当缺失的文本很重要时,请通过工具提示或展开视图保留完整值。

按字段选择。对用户需要完整识别项目的名称和标题进行包裹。当项目在末尾不同时(例如共享域名的文件名、路径和电子邮件),在中间进行截断,因为末尾的省略号会使它们看起来相同。切勿截断用户比较的数字、金额或日期。详情参见 wrapping-and-punctuation.md。

自然地书写文案,用 CSS 进行样式化

以自然大小写存储文本,并通过 text-transform 控制呈现方式,这样重新设计时就不必重写文案。

在渲染的文本中使用智能标点:

  • 散文中使用弯引号,代码中使用直引号。
  • 范围使用短破折号:2010–2020。
  • 单个省略号字符,而不是三个句点。
  • 使用   将 16 px 保持在换行符的两侧。
  • 使用 ­ 来指定长单词可以断开的位置。

使用字体自身的下划线

默认的下划线位于浏览器决定的任何位置。使用 text-underline-position: from-font 和 text-decoration-thickness: from-font 从字体自身的度量中提取位置和厚度。通过 text-decoration-thickness、text-underline-offset 和 text-decoration-skip-ink 手动调整。

text-decoration-style 可以将线条绘制为点线、虚线或波浪线。点线下划线是表示单词带有额外信息的常见提示,例如缩写或定义的术语。

颜色是真实下划线中唯一能可靠动画化的部分。因此,除非动画化的唯一内容是颜色,否则将下划线构建为独立的元素,而不是使用 text-decoration。

移动端输入框保持 16px

当输入框的文本小于 16px 时,iOS Safari 会缩放整个页面。有两种修复方法可以将输入框大小保持在 16px,但外观不同,因此请询问设计想要哪一种:

  • 在移动端将输入框放大(text-base sm:text-sm)。这改变了它在小屏幕上的外观。
  • 保持 font-size: 16px,并使用 transform: scale() 渲染目标大小,同时补偿宽度和 line-height。在每个视口下都相同,但需要更多代码维护。

两种方案均详见于 details-and-accessibility.md。

大小和对比度下限

将长篇正文文本从 16px 开始,即浏览器默认值。只有在有明确理由时才可以偏离:字体跑偏、行宽窄、或产品是密集的专业工具。

UI 文本可以更小。14px 是输入框和菜单的有用起点,13px 用于说明文字,很少低于 12px。输入框在移动端仍然需要 16px。

当文本看起来对比度低时,使用 hr-better-colors 测量渲染的对,并使用 hr-better-accessibility 对要求进行分类。除非被要求,否则不要修改颜色。

在根元素上开启字体平滑

在 macOS 上,文本渲染得比预期更粗。在根布局上一次性应用 -webkit-font-smoothing: antialiased 和 -moz-osx-font-smoothing: grayscale,切勿逐组件使用。Tailwind 的 antialiased 涵盖了这两者。

语言和双向行为

设置 lang,以便浏览器和辅助技术选择正确的发音、引号和断字。在文档级别或内容方向发生变化的内容边界设置 dir。保留数字顺序,并使用 <bdi> 隔离混合方向的值。空间镜像和逻辑 CSS 属性属于 hr-better-layout。

保持有用的文本可选

默认保持文本可选。::selection 可以将品牌带入阅读体验,只要所选组合保持可读。

user-select: none 适用于拖拽或手势驱动的表面,在这些地方意外选择会干扰操作。切勿在整个界面中使用,也切勿因为按钮标签可以被高亮而使用。

完成之前

错误修复
合成为的字形与设计不符加载真实字形;仅禁用已验证的合成模式
子标题在视觉上压制其父标题将该区域的层次结构映射到递减的比例步骤
因默认大小选择了标题元素首先选择语义,然后在 CSS 中设置大小
段落最后一行出现孤行text-wrap: pretty
不对称的两行标题text-wrap: balance
界面中文本两端对齐text-align: start;仅为特定编辑布局保留两端对齐
下划线穿过下行字母text-decoration-skip-ink: auto、from-font 度量
混合方向的值以错误顺序渲染纠正 lang/dir;使用 <bdi> 隔离该值
应用界面中禁用了选择功能恢复选择;仅在拖拽或手势冲突处禁用
额外信息提示没有视觉线索通过 text-decoration-style: dotted 使用点线下划线
14px UI 文本中使用细/轻字重18px 以下使用 weight 400+;细字重仅限显示用途
三行卡片描述中使用 leading-none任何包裹到 3+ 行的文本至少使用 1.4

报告

严重性。 HIGH 使文本不可读或截断内容且无法恢复。MEDIUM 破坏类型系统或标题层次结构。LOW 是孤立的打磨细节。

验证。 无浏览器时:检查每个标题级别的计算字号和字重,确保递减;检查声明的行高和行宽;根据实际字符串长度检查截断规则。有浏览器时:调整视口大小以捕捉真实内容长度下的换行、孤行和截断。将每个无法运行的检查报告为 未验证。

格式。 将发现按违反的原则分组,按严重性排序,每行一个根因,列出其出现的每个位置:

严重性位置之前之后原因

位置 是 path/to/file:line。原因 指出原则和用户影响。

当存在任何 HIGH 时报告 阻断,否则报告 批准,并将剩余问题留在表中作为待办事项。切勿批准你未检查的覆盖范围。无内容可报告时,注明“无可行的排版发现”并报告验证情况。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

相关技能