- 前端
- 开发工具
【免费下载链接】dillinger
The last Markdown editor, ever.
本篇技术指南以开源仓库中的移动端排版参考文档 .agent/skills/mobile-design/mobile-typography.md 为骨架,系统讲解移动端字体的设计基础、iOS/Android 系统字体体系、类型尺度、Dynamic Type 文本缩放、WCAG 无障碍要求、暗色模式排版以及字体加载性能优化。文中将结合 Dillinger 仓库实际的排版实现(tailwind.config.ts、app/globals.css)与自动化审计脚本 mobile_audit.py 进行纵深佐证。读完你能够:为 iOS/Android(React Native、Flutter 或原生)应用建立可缩放、可访问的排版体系,并具备对现有实现做排版审计的能力。
文档开宗明义地指出一个核心论断:排版失败是移动应用不可读的第一大原因(Typography failures are the #1 cause of unreadable mobile apps)。移动端排版不是装饰,而是用户与内容之间的主界面。
1. 移动端排版基础:为什么移动端与桌面端截然不同
1.1 移动端字体的差异根源
移动设备与桌面显示器的物理与交互环境存在本质差异,这是移动端排版设计的第一性原理。文档给出了如下对比:
DESKTOP: MOBILE: ├── 20-30" viewing distance ├── 12-15" viewing distance ├── Large viewport ├── Small viewport, narrow ├── Hover for details ├── Tap/scroll for details ├── Controlled lighting ├── Variable (outdoor, etc.) ├── Fixed font size ├── User-controlled sizing └── Long reading sessions └── Quick scanning四条关键差异直接决定了设计决策:
- 观看距离更近(12–15 英寸):同样的字号在近距观看下"看起来更大",但同时也意味着用户对字体的清晰度更敏感,抗锯齿与字重渲染质量要求更高;
- 视口更小更窄:每行能容纳的字符数急剧下降,正文行宽必须控制在 40–60 字符,否则换行过于频繁、阅读追踪困难;
- 环境光照不可控:用户可能在户外强光下使用,低对比度文本会"隐形",因此对比度要求比桌面更严格(AA 为底线,AAA 更优);
- 字号由用户控制:iOS 的 Dynamic Type 与 Android 的字体缩放(85%–200%)意味着开发者无法假定某个固定 px 值在用户设备上成立,排版必须"可缩放"。
1.2 移动端排版规则速查表
| 规则 | 桌面端 | 移动端 |
|---|---|---|
| 最小正文字号 | 14px | 16px(14pt/14sp) |
| 最大行长 | 75 字符 | 40–60 字符 |
| 行高 | 1.4–1.5 | 1.4–1.6(更宽松) |
| 字重 | 多样 | Regular 为主,粗体克制使用 |
| 对比度 | AA(4.5:1) | AA 为最低要求,AAA 优先 |
移动端的核心心法是"Regular 字重主导 + 粗体克制"。从 Dillinger 的预览排版实现 app/globals.css 可以看到同样的思路:正文
font-size: 14px; line-height: 1.7,标题统一使用font-weight: 600(Semibold 而非更重的 Bold),通过字号与行距而非字重爆炸来建立层级。
2. 系统字体:iOS 与 Android 的字体体系
2.1 iOS:SF Pro 家族
iOS 的系统字体是 San Francisco(SF)家族,按用途分为五个子族:
San Francisco (SF) Family: ├── SF Pro Display: 大号文本(≥ 20pt) ├── SF Pro Text: 正文文本(< 20pt) ├── SF Pro Rounded: 友好/趣味场景 ├── SF Mono: 等宽字体 └── SF Compact: Apple Watch、紧凑界面SF Pro 的核心特性:
- 光学尺寸(Optical sizing):字体根据实际渲染字号自动切换 Display/Text 形态,保证大标题与正文各自的最优字面比例;
- 动态字距(Dynamic tracking):字母间距随字号动态调整,大字号自动收紧、小字号自动放宽,弥补大字号视觉上"字距偏松"的错觉;
- 表格/比例数字(Tabular/proportional figures):适合数据表格与正文两种场景;
- 出色的易读性(Excellent legibility):专为屏幕渲染优化。
2.2 Android:Roboto 家族
Android 的系统字体是 Roboto,同样是一个完整家族:
Roboto Family: ├── Roboto: 默认无衬线字体 ├── Roboto Flex: 可变字体(variable font) ├── Roboto Serif: 衬线选项 ├── Roboto Mono: 等宽 ├── Roboto Condensed: 窄空间Roboto 的特性:
- 针对屏幕优化(Optimized for screens):在低分辨率与 OLED 屏幕上都有良好表现;
- 广泛的语言支持(Wide language support):适合全球化应用;
- 多字重(Multiple weights):覆盖 100–900 全部字重;
- 小字号表现佳(Good at small sizes):小字号下笔画依然清晰可辨。
2.3 何时使用系统字体:决策清单
✅ 应该使用系统字体的场景:
├── 品牌没有强制要求自定义字体 ├── 阅读效率是首要目标 ├── 应用需要"原生/融为一体"的感觉 ├── 性能是关键约束(零下载成本) ├── 需要广泛的语言支持❌ 应避免系统字体的场景:
├── 品牌形象要求自定义字体 ├── 需要通过字体实现设计差异化 ├── 编辑/杂志风格(editorial/magazine style) └── (即便如此,也必须支持无障碍缩放)2.4 自定义字体的考量清单
如果决定使用自定义字体,必须逐项确认:
If using custom fonts: ├── 包含所有需要的字重(Include all weights needed) ├── 子集化以控制文件体积(Subset for file size) ├── 在所有 Dynamic Type 字号下测试(Test at all Dynamic Type sizes) ├── 提供系统字体回退(Provide fallback to system) ├── 测试渲染质量(Test rendering quality) └── 检查语言支持(Check language support)仓库佐证:系统字体回退栈的工程化落地在 Dillinger 的 tailwind.config.ts 中,字体族被定义为多层回退栈,这正是"自定义字体 + 系统字体兜底"原则的 Web 端实现:
fontFamily: { sans: ['"Source Sans Pro"', '"Helvetica Neue"', "Helvetica", "Arial", "sans-serif"], serif: ["Georgia", "Cambria", "serif"], mono: ['"Ubuntu Mono"', "Monaco", "monospace"], },每个字体族的第一项是品牌自定义字体(Source Sans Pro / Georgia / Ubuntu Mono),随后紧跟平台原生字体(Helvetica Neue / Monaco)与通用字体族兜底。当自定义字体加载失败或缺失某字符时,浏览器会平滑降级到系统字体,用户依然能获得可读的排版——这与移动端"自定义字体必须提供系统回退"的要求完全同构。
3. 类型尺度:iOS、Material 3 与自定义模块化比例
3.1 iOS 内建类型尺度(Dynamic Type 文本样式)
iOS 提供 11 级内建文本样式,随用户系统设置自动缩放:
| 样式 | 字号 | 字重 | 行高 |
|---|---|---|---|
| Large Title | 34pt | Bold | 41pt |
| Title 1 | 28pt | Bold | 34pt |
| Title 2 | 22pt | Bold | 28pt |
| Title 3 | 20pt | Semibold | 25pt |
| Headline | 17pt | Semibold | 22pt |
| Body | 17pt | Regular | 22pt |
| Callout | 16pt | Regular | 21pt |
| Subhead | 15pt | Regular | 20pt |
| Footnote | 13pt | Regular | 18pt |
| Caption 1 | 12pt | Regular | 16pt |
| Caption 2 | 11pt | Regular | 13pt |
注意观察两个细节:行高始终约为字号的 1.2–1.3 倍(如 Body 17pt/22pt ≈ 1.29),这与第 5 节无障碍行高的推荐一致;同时标题字号从 34pt 到 17pt 逐级递减,形成清晰的层级梯度。
3.2 Android 类型尺度(Material 3)
Material Design 3 定义了 15 个文本角色(Text Role),以 sp 为单位:
| 角色 | 字号 | 字重 | 行高 |
|---|---|---|---|
| Display Large | 57sp | 400 | 64sp |
| Display Medium | 45sp | 400 | 52sp |
| Display Small | 36sp | 400 | 44sp |
| Headline Large | 32sp | 400 | 40sp |
| Headline Medium | 28sp | 400 | 36sp |
| Headline Small | 24sp | 400 | 32sp |
| Title Large | 22sp | 400 | 28sp |
| Title Medium | 16sp | 500 | 24sp |
| Title Small | 14sp | 500 | 20sp |
| Body Large | 16sp | 400 | 24sp |
| Body Medium | 14sp | 400 | 20sp |
| Body Small | 12sp | 400 | 16sp |
| Label Large | 14sp | 500 | 20sp |
| Label Medium | 12sp | 500 | 16sp |
| Label Small | 11sp | 500 | 16sp |
规律:Display/Headline/Title/Body 四档以 400 常规字重为主,Label 与 Title Medium/Small 使用 500 中字重以承担按钮、标签等功能性文本。
3.3 自定义类型尺度:模块化比例(Modular Ratio)
iOS 与 Android 的内建尺度覆盖了绝大多数场景,但当品牌需要自定义尺度时,应使用数学化的模块化比例生成字号,而不是随手挑数值。推荐比例:
Recommended ratios: ├── 1.125 (Major second 大二度): 密集 UI ├── 1.200 (Minor third 小三度): 紧凑 ├── 1.250 (Major third 大三度): 均衡(常用) ├── 1.333 (Perfect fourth 纯四度): 宽敞 └── 1.500 (Perfect fifth 纯五度): 戏剧化以 1.25 比例、16px 基准的完整示例:
├── xs: 10px (16 ÷ 1.25 ÷ 1.25) ├── sm: 13px (16 ÷ 1.25) ├── base: 16px ├── lg: 20px (16 × 1.25) ├── xl: 25px (16 × 1.25 × 1.25) ├── 2xl: 31px ├── 3xl: 39px └── 4xl: 49px仓库佐证:模块化比例的姊妹文档仓库中另一份前端排版文档 .agent/skills/frontend-design/typography-system.md 系统阐述了同一原理:选定基准字号(正文通常 16–18px)与比例(移动应用常用 1.2 小三度、Web 常用 1.25 大三度),然后用
base × ratio^n生成整条尺度。这也印证了审计脚本对"字号是否遵循模块化比例"的检查逻辑(见第 4 节 9.3 检查项)。
4. Dynamic Type 与文本缩放(MANDATORY 强制要求)
4.1 iOS Dynamic Type:必须使用语义化文本样式
iOS 的 Dynamic Type 允许用户全局调整系统字号,应用必须跟随这一设置。错误示范是写死固定字号:
// ❌ WRONG: Fixed size (doesn't scale) Text("Hello") .font(.system(size: 17)) // ✅ CORRECT: Dynamic Type Text("Hello") .font(.body) // Scales with user setting // 自定义字体也要声明相对尺度 Text("Hello") .font(.custom("MyFont", size: 17, relativeTo: .body))即使使用自定义字体,也必须通过relativeTo:将其锚定到某个内建文本样式上,才能随 Dynamic Type 缩放。
4.2 Android 文本缩放:必须使用 sp 单位
Android 侧的唯一铁律是:文本一律使用 sp(Scale-independent Pixels)。
ALWAYS use sp for text: ├── sp = Scale-independent pixels(与缩放无关的像素) ├── 随用户字体偏好缩放 ├── dp 不缩放(不要用于文本)用户可将系统字体从 85% 缩放到 200%:
├── 默认(100%): 14sp = 14dp ├── 最大(200%): 14sp = 28dp必须在 200% 下测试布局!一个 14sp 的文本在最大缩放时会占用 28dp 的空间,固定高度的容器必然溢出。
4.3 文本缩放带来的布局挑战与对策
大字号下常见的问题:
Problems at large text sizes: ├── 文本溢出容器(Text overflows containers) ├── 按钮变得过高(Buttons become too tall) ├── 图标相对文本显得过小(Icons look small relative to text) ├── 布局崩溃(Layouts break) Solutions: ├── 使用弹性容器,不要固定高度(Use flexible containers) ├── 允许文本换行(Allow text wrapping) ├── 图标随文本缩放(Scale icons with text) ├── 开发期间就在极端尺寸下测试(Test at extremes) ├── 长文本使用可滚动容器(Use scrollable containers)仓库佐证:审计脚本如何自动检查缩放支持移动端审计脚本 .agent/skills/mobile-design/scripts/mobile_audit.py 的 4.2 检查项专门扫描 React Native 代码:一旦检测到
fontSize:存在但没有任何allowFontScaling: true/responsiveFontSize/useWindowDimensions缩放机制,就会给出警告:[Typography] {filename}: Fixed font sizes without scaling support. Consider allowFontScaling for accessibility.该脚本还检查行高上限(
lineHeight超过 1.8 会被标记"对移动端过高")、字号下限(小于 12px 触发可读性警告)与上限(大于 32px 建议改用响应式缩放),详见 mobile_audit.py。这意味着"缩放支持"不仅是设计原则,还可以作为 CI 中可量化的审计项。
5. 排版无障碍:最小尺寸、对比度与行高
5.1 最小字号表
| 元素 | 最小 | 推荐 |
|---|---|---|
| 正文(Body text) | 14px/pt/sp | 16px/pt/sp |
| 次要文本(Secondary text) | 12px/pt/sp | 13–14px/pt/sp |
| 注释(Captions) | 11px/pt/sp | 12px/pt/sp |
| 按钮(Buttons) | 14px/pt/sp | 14–16px/pt/sp |
| 任何内容不得小于 | 11px | - |
5.2 WCAG 对比度要求
普通文本(< 18pt 或 < 14pt 粗体): ├── AA: 对比度 ≥ 4.5:1(最低要求) ├── AAA: 对比度 ≥ 7:1(推荐) 大号文本(≥ 18pt 或 ≥ 14pt 粗体): ├── AA: 对比度 ≥ 3:1(最低要求) ├── AAA: 对比度 ≥ 4.5:1(推荐) Logo/装饰性元素: 无要求5.3 无障碍行高(WCAG 1.4.12 成功准则)
WCAG 对文本间距有明确的量化要求:
Line height(行距): ≥ 1.5× 字号 Paragraph spacing(段距): ≥ 2× 字号 Letter spacing(字距): ≥ 0.12× 字号 Word spacing(词距): ≥ 0.16× 字号移动端推荐值:
├── 正文: 行高 1.4–1.6 ├── 标题: 行高 1.2–1.3 ├── 任何文本不得低于 1.2仓库佐证:Dillinger 预览排版的行高实践在 app/globals.css 中,Dillinger 的 Markdown 预览正文设置了
line-height: 1.7,高于 WCAG 的 1.5 下限、落入移动端推荐区间(1.4–1.6 之上),适合长文阅读;标题则通过margin-top: 1.5em; margin-bottom: 0.5em保证段落间距达到 2× 字号的量级(对应 WCAG 段距要求)。这种"正文宽松、标题紧凑"的层次与移动端推荐完全一致。
6. 暗色模式排版
6.1 颜色调整原则
Light Mode: Dark Mode: ├── 黑色文本 (#000) ├── 白色/浅灰文本 (#E0E0E0) ├── 高对比度 ├── 略降低的对比度 ├── 全饱和度 ├── 去饱和的颜色 └── 深色 = 强调 └── 浅色 = 强调铁律:暗色模式下不要使用纯白(#FFF)。应使用介于 #E0E0E0 到 #F0F0F0 之间的米白(off-white)来减轻眼部疲劳。
6.2 暗色模式层级色表
| 层级 | 亮色模式 | 暗色模式 |
|---|---|---|
| 主文本(Primary text) | #000000 | #E8E8E8 |
| 次文本(Secondary text) | #666666 | #A0A0A0 |
| 三级文本(Tertiary text) | #999999 | #707070 |
| 禁用文本(Disabled text) | #CCCCCC | #505050 |
6.3 暗色模式下的字重策略
暗色背景下文本会因**光晕效应(halation,浅色光渗入深色背景)**而显得更细,因此需要:
Consider: ├── 正文使用中字重(medium)替代常规字重(regular) ├── 略微增加字母间距(letter-spacing) ├── 在真实 OLED 屏幕上测试 └── 使用比亮色模式略粗的字重仓库佐证:Dillinger 暗色排版的落地细节Dillinger 在 app/globals.css 中为暗色预览定义了
.dark.preview-html { color: #d4d4d4; }——注意它不是纯白 #FFFFFF,而是接近文档推荐的 #E0E0E0 区间,直接呼应"暗色模式禁用纯白"的规则。标题颜色 #e8e8e8、链接保持品牌色 #35D7BB、代码块背景 #2d2d2d 且前景 #d4d4d4,均体现了"降低对比但不牺牲可读性"的暗色排版策略。项目通过darkMode: "class"(tailwind.config.ts)按类切换暗色样式,移动端对应useColorScheme的系统外观监听。
7. 排版反模式:常见错误与 AI 特有错误
7.1 常见错误对照表
| 错误 | 问题 | 修复 |
|---|---|---|
| 固定字号(Fixed font sizes) | 无视无障碍 | 使用动态缩放 |
| 文本过小(Too small text) | 不可读 | 最小 14pt/sp |
| 低对比度(Low contrast) | 阳光下不可见 | 最小 4.5:1 |
| 过长行(Long lines) | 难以追踪 | 最大 60 字符 |
| 行高过紧(Tight line height) | 拥挤、难读 | 最小 1.4× |
| 字号过多(Too many sizes) | 视觉混乱 | 最多 5–7 个字号 |
| 正文全大写(All caps body) | 难读 | 仅用于标题 |
| 白底浅灰(Light gray on white) | 强光下不可读 | 提高对比度 |
7.2 AI 生成的排版为何经常出错
AI 生成移动端代码时存在系统性倾向:
AI tends to: ├── 使用固定 px 值而非 pt/sp ├── 跳过 Dynamic Type 支持 ├── 正文过小(12–14px) ├── 忽略行高设置 ├── 使用低对比度的"审美灰" ├── 将桌面尺度原样套用到移动端 └── 跳过在大字号下的测试最终规则:排版必须可缩放(Typography must SCALE),在最小与最大字号设置下都要测试。
仓库佐证:审计脚本对 AI 反模式的机器化识别mobile_audit.py 的 9.x 扩展检查组几乎逐条对应上述反模式:9.1 检查字号是否偏离 iOS 类型尺度、9.2 检查 Material 排版是否使用 sp 单位、9.3 检查字号是否遵循模块化比例(识别 1.125/1.2/1.25/1.333/1.5 之外的异常比率)、9.4 检查长文本是否缺少最大宽度约束(对应 40–60 字符行宽)、9.5 检查粗体是否过度使用(bold 数量多于 regular 会被标记)。这让排版反模式检查具备了自动化落地手段。
8. 字体加载与性能
8.1 字体文件体积优化
字体文件在移动端是明显的性能负担:
Font file sizes matter on mobile: ├── 完整字体: 每个字重 100–300KB ├── 子集化(拉丁文): 每个字重 15–40KB ├── 可变字体: 100–200KB(覆盖全部字重)推荐做法:
├── 子集化到需要的字符(Subset to needed characters) ├── 使用 WOFF2 格式 ├── 最多 2–3 个字体文件 ├── 考虑可变字体(variable fonts) ├── 合理缓存字体8.2 加载策略:四步法
1. SYSTEM FONT FALLBACK(系统字体回退) 先显示系统字体 → 自定义字体加载完成后替换 2. FONT DISPLAY SWAP font-display: swap(CSS 声明) 3. PRELOAD CRITICAL FONTS(预加载关键字体) 预加载首屏(above the fold)需要的字体 4. DON'T BLOCK RENDER(不要阻塞渲染) 不要为了等字体而延迟内容显示仓库佐证:零字体加载开销的 Web 端策略Dillinger 作为一个以编辑效率为核心的应用,其 tailwind.config.ts 声明的字体栈首项(Source Sans Pro、Georgia、Ubuntu Mono)即使未能加载,也会立即回退到系统字体,天然实现了"系统字体先行、自定义字体渐进增强"的策略——这正是"不阻塞渲染 + 系统回退"在 Web 平台的等价实现。对移动端开发者而言,这条策略对应 SwiftUI 的
.font(.custom(..., relativeTo: ...))与 Compose 的FontFamily回退参数。
9. 发布前排版检查清单
9.1 任何文本设计开始之前
- 正文 ≥ 16px/pt/sp?
- 行高 ≥ 1.4?
- 行长 ≤ 60 字符?
- 定义了类型尺度(最多 5–7 个字号)?
- 使用 pt(iOS)或 sp(Android)?
9.2 发布之前
- iOS Dynamic Type 已测试?
- Android 在 200% 字体缩放下已测试?
- 暗色模式对比度已检查?
- 阳光下可读性已测试?
- 所有文本都有正确的层级?
- 自定义字体有回退方案?
- 长文本可正常滚动?
落地建议:把清单变成自动化审计仓库提供的 mobile_audit.py 可以帮你把大部分检查项自动化。其用法(见脚本 main 函数)为:
python scripts/mobile_audit.py <project_path> # 输出人类可读报告 python scripts/mobile_audit.py <project_path> --json # 输出 JSON 报告,便于 CI 集成脚本自动识别 React Native / Flutter 文件(通过 import 特征),跳过 node_modules 等目录,输出 ISSUES(硬性问题,如 ScrollView+map、缺 keyExtractor、明文存 token)与 WARNINGS(建议项,如固定字号无缩放、缺 React.memo、无暗色模式支持)两级报告,其中排版相关检查覆盖系统字体、文本缩放、行高、字号边界、模块化比例、行宽与字重分布(脚本头部注释 mobile_audit.py 列出了完整的检查矩阵)。退出码非零即表示存在硬性问题,可直接挂入 CI 门禁。
10. 快速参考
10.1 排版令牌(Typographic Tokens)
// iOS(SwiftUI 内建样式) .largeTitle // 34pt, Bold .title // 28pt, Bold .title2 // 22pt, Bold .title3 // 20pt, Semibold .headline // 17pt, Semibold .body // 17pt, Regular .subheadline // 15pt, Regular .footnote // 13pt, Regular .caption // 12pt, Regular // Android(Material 3 文本角色) displayLarge // 57sp headlineLarge // 32sp titleLarge // 22sp bodyLarge // 16sp labelLarge // 14sp10.2 最小字号速查
Body: 14–16pt/sp(推荐 16) Secondary: 12–13pt/sp Caption: 11–12pt/sp 任何文本: 不得小于 11pt/sp10.3 行高速查
Headings: 1.1–1.3 Body: 1.4–1.6 Long text: 1.5–1.75结语:排版即界面
原文档在结尾给出了移动端排版设计的最终判据:如果用户读不懂你的文本,你的应用就是坏的。排版不是装饰——它是主界面(Typography isn't decoration—it's the primary interface)。要在真实设备、真实光照、无障碍设置开启的状态下测试。
将这份指南落到 Dillinger 仓库的语境中可以看到一条完整的证据链:设计文档 mobile-typography.md 定义原则 → 前端排版文档 typography-system.md 给出模块化比例的生成方法 → 审计脚本 mobile_audit.py 将原则量化为可自动执行的检查 → Web 端实现 tailwind.config.ts 与 app/globals.css 提供了"系统字体回退栈 + 宽松行高 + 暗色米白文本"的真实范例。无论你正在构建 React Native、Flutter 还是原生应用,都可以以此为模板:定义类型尺度 → 锚定系统缩放 → 通过审计 → 在极端字号下测试,让排版真正成为用户可读、可缩放、可访问的界面基础设施。
- 前端
- 开发工具
【免费下载链接】dillinger
The last Markdown editor, ever.
相关推荐
ag-kit 移动排版完全指南:Type Scale、系统字体、Dynamic Type、深色模式与可访问性验证
ag kit 移动排版完全指南:Type Scale、系统字体、Dynamic Type、深色模式与可访问性验证 本篇技术指南以 ag kit 技能库中 mob
人工智能AI 技能Logoly无障碍字体选择:确保可读性与可访问性的字体
Logoly无障碍字体选择:确保可读性与可访问性的字体 在数字产品设计中,字体选择不仅关乎视觉美感,更是确保所有用户(包括残障用户)能够有效获取信息的关键环节。
前端mailcheck.js无障碍字体选择:提升可读性
mailcheck.js无障碍字体选择:提升可读性 引言 在当今数字化时代,网页的可访问性(Accessibility,简称A11y)日益受到重视。对于邮件验证
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考