图像与设计
审查或实现跨产品排版时:用字体、字号、行高、换行、截断与…
适用于前端/产品界面和长文的排版审查与实现,解决字体选择、字号层级、行高、换行、截断、数字对齐、下划线及可访问性细节问题。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
审查或实现跨产品排版时:用字体、字号、行通用
解决思路
- 审查时阅读渲染后的页面,而不是只扫代码;坏换行、孤行和截断只有在真实内容长度下才会显现。
- 把每个修复写进项目的样式系统,并使用下文的精确值,而不是看起来相近的等价物;[css-cheat-sheet.md] 将每条声明映射到其 Tailwind 等价物。
- 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` 会关闭合成,但会抹掉强调而不是报告它;只在检查所有必需的 bold、italic、small-cap、superscript 和 subscript 形式在回退字体栈中仍保持可区分之后才设置它。
- 很少使用超过三种字体。
- 字重和字号定义层级;过度使用会迅速损害可读性。
- 配对字体要追求对比,而不是相似:衬线标题配无衬线正文显得有意为之,两个几乎相同的无衬线字体则像错误。
- 在 `18px` 以下,保持字重 `400` 或更重。
- 低于 `300` 的字重只在 `28px`+ 的展示文本使用;在正文尺寸会消失。
- 配对指导见 choosing-fonts.md。
- 定义一小组字号,并尽量少偏离。
- 没有系统支撑的硬编码字号在规模化时会崩溃。
- 单人项目且使用规则清晰时,像 `text-sm` 这样的默认名称可以。
- 团队中使用按用途命名的字号(如 `text-body-sm`),让规则在他人手中也能延续。字号体系构建见 spacing-and-sizing.md。
- 将标题级别映射到字号体系的递减层级,使视觉上从属的标题永远不会压过父级。
- 相邻层级在字号较小端可以共享字号,只要字重或间距让它们保持区分。
- 语义元素属于 better-accessibility;此技能只设置视觉处理。
- 标题行高更紧,约 `1.1`。
- 正文行高 `1.5` 到 `1.6`。
- 优先使用无单位值,让行高随字号缩放;固定 `24px` 不会。
- 紧行高用于短文本;任何会换行到三行或更多的文本至少需要 `1.4`,即使在高度受限的行中。
- 大标题通常适合稍微负的 letter-spacing。
- 小号全大写标签需要一点正 letter-spacing,否则字母会显得拥挤。
- 阅读尺寸的正文两者都不需要。
- 限制长文副本文本约每行 `60–75` 个字符。
- 任何单位都可以,只要存在上限且行长落在此范围内。见 wrapping-and-punctuation.md#measure-line-length。
- `text-wrap: balance` 在多行间均匀分配文本;用在标题上。
- `text-wrap: pretty` 阻止单个短词落到最后一行;用在描述上。
- 在长词、链接或 ID 可能溢出容器的地方使用 `overflow-wrap: break-word`。
- 在换行会显得破裂的标签和徽章上使用 `white-space: nowrap`。
- 在长文中跳过 `balance` 和 `pretty`。
- 数字默认宽度不同,所以计时器、计数器和价格更新时会移动布局;对任何会变化的值应用 `font-variant-numeric: tabular-nums`。
- 单行截断:`text-overflow: ellipsis` 配合 `overflow: hidden` 和 `white-space: nowrap`。
- 多行截断使用 `line-clamp`。
- 截断会隐藏内容;当缺失文本重要时,在 tooltip 或展开视图中保留完整值可访问。
- 文本以自然大小写存储,并用 `text-transform` 控制呈现,这样改版永远不需要重写文案。
- 渲染文本中使用智能标点:正文用弯引号,代码用直引号。
- 范围使用 en dash:`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`。
- iOS Safari 在输入框文本小于 `16px` 时会缩放整个页面。
- 两种修复都把尺寸保持在 `16px` 且外观不同,所以询问设计想要哪一种:移动端放大输入框(`text-base sm:text-sm`),会改变小屏外观。
- 或者保持 `font-size: 16px`,并用 `transform: scale()` 渲染预期尺寸,同时补偿宽度和 `line-height`;每个视口都一致,但维护代码更多。两个配方见 details-and-accessibility.md。
- 长正文从 `16px` 开始(浏览器默认);只有能说出原因时才偏离:字体偏小、行宽窄或产品是高密度专业工具。
- UI 文本可以更小:输入框和菜单从 `14px` 开始有用,说明文字 `13px`,很少低于 `12px`。输入框在移动端仍需要 `16px`。
- 当文本看起来低对比度时,用 better-colors 测量渲染后的配对,用 better-accessibility 分类要求;除非被要求,否则不要改颜色。
- 在 macOS 上文本渲染比预期更重;在根布局上应用一次 `-webkit-font-smoothing: antialiased` 和 `-moz-osx-font-smoothing: grayscale`,绝不在每个组件上应用。Tailwind 的 `antialiased` 覆盖两者。
- 设置 `lang`,让浏览器和辅助技术选择正确发音、引号和连字符。
- 在文档或方向变化的内容边界上设置 `dir`。
- 保留数字顺序,并使用 `<bdi>` 隔离混合方向的值。
- 空间镜像和逻辑 CSS 属性属于 better-layout。
- 默认保持文本可选中。
- `::selection` 可以把品牌带入阅读体验,只要选中组合保持清晰可读。
- `user-select: none` 属于拖拽或手势驱动的表面,意外选中会干扰操作;绝不要在整个界面使用,也绝不要因为按钮标签可高亮而使用。
- 合成字形与设计不同 -> 加载真实字形;只禁用已验证的合成模式。
- 子标题视觉上压过父级 -> 将该区块层级映射到递减的字号体系层级。
- 标题元素按默认字号选择 -> 先选语义,再用 CSS 设置字号。
- 段落最后一行出现孤儿 -> `text-wrap: pretty`。
- 两行标题左右不平衡 -> `text-wrap: balance`。
- 界面中使用两端对齐文本 -> `text-align: start`;justify 只保留给特定编辑排版。
- 下划线穿过下伸部 -> `text-decoration-skip-ink: auto`,使用 `from-font` 度量。
- 混合方向值排序错误 -> 修正 `lang`/`dir`;用 `<bdi>` 隔离该值。
- 整个应用界面禁用选择 -> 恢复选择;只在拖拽或手势冲突处抑制。
- 额外信息提示没有视觉线索 -> 用 `text-decoration-style: dotted` 画点状下划线。
- 在 `14px` UI 文本上使用 Thin/Light 字重 -> `18px` 以下使用 `400+` 字重;细字重仅用于展示。
- 三行卡片描述上使用 `leading-none` -> 任何换行到 3+ 行的文本至少 `1.4`。
- 报告严重性:`HIGH` 使文本不可读或截断内容且无法恢复;`MEDIUM` 破坏字体系统或标题层级;`LOW` 是孤立打磨。
- 无浏览器验证:检查每个标题级别的计算后字号和字重,确认递减;检查声明的 line-height 和行宽;用现实字符串长度检查截断规则。
- 有浏览器验证:调整视口大小,在真实内容长度下捕捉换行、孤行和截断。将每个未能运行的检查报告为 `Not verified`。
- 报告格式:按违反的原则分组,按严重性排序,每个根因一行,列出其出现的每个位置;表格列为 `Severity | Location | Before | After | Why`。
- `Location` 为 `path/to/file:line`;`Why` 命名原则和用户影响。
- 当仍有任何 `HIGH` 时以 `Block` 结束,否则以 `Approve` 结束,把其余留在表中作为待办;绝不 `Approve` 未检查的覆盖范围。
- 没有可报告的内容时,声明 `No actionable typography findings` 并报告验证情况。
适用边界 · 注意事项
- 文案撰写本身、语义标题结构与无障碍判定不适用,分别交给 better-writing 和 better-accessibility。
- 空间 RTL 镜像布局和逻辑 CSS 属性不适用,交给 better-layout。
- 颜色对比度测量不适用,交给 better-colors。