npx skills add https://github.com/wondelai/skills --skill web-typography一份关于为网页选择、配对和实现字体的实用指南。排版服务于沟通——最好的排版是隐形的,让读者沉浸在内容中,而不是吸引注意力到自身。
排版是您内容的声音。 您选择的字体在阅读第一个字之前就设定了基调。一个法律网站不应该显得有趣;一个儿童应用不应该显得企业化。
"透明酒杯"原则: 排版应该像一个晶莹剔透的酒杯——焦点在酒(内容)上,而不是杯子(字体)。读者应该吸收意义,而不是注意到字形。
读者不阅读,他们扫描。 眼睛每次跳跃7-9个字符(扫视),短暂停顿(注视)。好的排版支持这种自然模式。
目标:10/10。 在审查或创建排版实现时,根据对以下原则的遵循程度,给它们打0-10分。10/10表示完全符合所有指导方针;较低的分数表示需要解决的差距。始终提供当前分数以及达到10/10所需的具体改进。
所有排版都分为两类:
| 情境 | 目的 | 优先级 |
|---|---|---|
| 瞬间字体 | 标题、按钮、导航、徽标 | 个性、影响力、独特性 |
| 长久相伴字体 | 正文、文章、文档 | 可读性、舒适度、持久性 |
主力字体 擅长"长久相伴字体"——它们在不同尺寸、字重和情境下都通用,不会吸引注意力到自身。例如:Georgia、Source Sans、Freight Text、FF Meta。
核心理念: 理解阅读机制是每个排版决策的基础。眼睛不是平滑扫描的——它们是跳跃式移动的,好的排版支持这种自然模式。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
为何有效: 当排版与大脑处理文本的方式(通过单词形状识别、一致的节奏和清晰的字形区分)保持一致时,读者能更快地吸收内容且更少疲劳。违背这些机制会产生摩擦,导致读者流失。
关键见解:
产品应用:
| 情境 | 应用 | 示例 |
|---|---|---|
| 长篇内容 | 为持续阅读舒适度优化 | 16-18px 正文,1.5-1.7 行高,45-75 字符行 |
| 仪表板 UI | 为快速扫描优化 | 清晰的字重层级,数据组间充足的留白 |
| 移动端阅读 | 考虑可变距离和光照 | 稍大的正文尺寸(17-18px),更高的对比度 |
| 文档 | 支持扫描和深度阅读 | 清晰的标题层级,宽松的段落间距 |
| 电子商务 | 实现快速产品比较 | 一致的数字格式,表格数字 |
| 无障碍性 | 支持不同能力的读者 | 高对比度,宽松间距,清晰的字形 |
复制模式:
/* 正文的最佳阅读节奏 */
.prose {
font-size: 1.125rem; /* 18px */
line-height: 1.6;
max-width: 65ch; /* ~45-75 字符 */
letter-spacing: normal; /* 不要在正文上强制调整字距 */
}
道德边界: 排版决策应始终优先考虑读者的理解和舒适度,而不是视觉新颖性。为了美学效果而牺牲可读性会排除读者并破坏内容的目的。
参见:references/typeface-anatomy.md 了解术语、字形部件和分类系统。
核心理念: 字体在获得项目中的位置之前,必须通过技术、结构和实用的质量检查。漂亮的样本在屏幕上可能失败;严格的评估可以防止项目中期更换字体带来的高昂代价。
为何有效: 屏幕渲染、可变带宽和多样化的设备带来了印刷从未面临的限制。通过结构评估(一致的笔画、开放的字怀、清晰的字形)和实用评估(文件大小、许可证、渲染)的字体将在各种现实条件下可靠地表现。
关键见解:
产品应用:
| 情境 | 应用 | 示例 |
|---|---|---|
| 正文选择 | 优先考虑x高度、开放字怀、均匀颜色 | 对于长篇阅读,选择Source Serif Pro而非Didot |
| 标题选择 | 优先考虑大尺寸下的个性和独特性 | Playfair Display用于编辑影响力 |
| UI/系统文本 | 优先考虑小尺寸下的易认性和字重范围 | Inter或SF Pro用于界面元素 |
| 多语言产品 | 验证目标语言的完整字形覆盖 | Noto Sans用于广泛的Unicode支持 |
| 性能关键站点 | 评估文件大小和子集选项 | 可变字体单文件 vs 多个静态字重 |
| 品牌更新 | 评估字体是否传达预期的个性 | 在实际使用尺寸下比较样本与品牌属性 |
复制模式:
/* 在实际使用尺寸下测试字体 */
body { font-size: 16px; } /* 最小正文尺寸 */
.caption { font-size: 0.75rem; } /* 压力测试小尺寸 */
h1 { font-size: 3rem; } /* 检查大尺寸字符 */
/* 使用字体平滑验证渲染 */
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
道德边界: 在实施前始终验证字体许可证。使用未经许可的字体会使项目面临法律风险,并损害创建这些工具的字型设计社区。
参见:references/evaluating-typefaces.md 了解详细的质量评估标准和结构分析。
核心理念: 从目的出发,而不是美学。内容的基调、阅读情境、持续时间和个性应驱动字体选择——而不是个人偏好或追随潮流。
为何有效: 当字体选择基于内容需求时,结果感觉是必然的,而不是任意的。目的驱动的选择也更容易通过利益相关者审查,因为它们可以用清晰的推理而非主观品味来证明其合理性。
关键见解:
产品应用:
| 情境 | 应用 | 示例 |
|---|---|---|
| 内容密集型站点 | 选择主力衬线体或无衬线体用于持续阅读 | Source Serif Pro或Charter用于文章 |
| SaaS仪表板 | 选择具有强大表格数字的简洁无衬线体 | Inter或IBM Plex Sans用于数据丰富的界面 |
| 营销落地页 | 将独特的展示字体与可读的正文字体配对 | Playfair Display标题 + Source Sans Pro正文 |
| 文档站点 | 优先考虑代码+散文的清晰度和字重范围 | IBM Plex Mono用于代码,IBM Plex Sans用于散文 |
| 品牌驱动产品 | 委托或授权体现品牌价值的字体 | 自定义字体或精心选择匹配品牌个性的字体 |
| 无障碍优先 | 选择为最大易认性设计的字体 | Atkinson Hyperlegible用于视力受损用户 |
复制模式:
/* 安全的系统字体栈 */
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI',
Roboto, Oxygen, Ubuntu, sans-serif;
}
/* 可靠的网页字体正文栈 */
body {
font-family: 'Source Sans Pro', -apple-system,
BlinkMacSystemFont, sans-serif;
}
道德边界: 避免仅为了显得时尚或复杂而选择字体,牺牲可读性。为了视觉风格而排除视力较低或阅读困难的读者的排版,未能实现其基本目的。
参见:references/evaluating-typefaces.md 了解选择过程中应用的质量评估。
核心理念: 成功的字体配对创造清晰的对比——字体应该明显不同,而不是令人困惑地相似。最多一到两种字体;更多需要非凡的技巧。
为何有效: 字体之间的对比创造了视觉层次和节奏。当两种字体过于相似时,它们会产生无目的的紧张感——读者感觉到有些"不对劲",但不知道为什么。清晰的结构对比(衬线体+无衬线体、细体+常规体、人文主义体+几何体)让每种字体在和谐共存的同时扮演不同的角色。
关键见解:
产品应用:
| 情境 | 应用 | 示例 |
|---|---|---|
| 编辑站点 | 衬线体标题 + 无衬线体正文,实现经典可读性 | Playfair Display + Source Sans Pro |
| 科技产品 | 超级字族保证和谐 | Roboto + Roboto Slab |
| 企业站点 | 同一设计师配对实现微妙凝聚力 | FF Meta + FF Meta Serif |
| 电子商务 | 独特的展示字体 + 中性正文 | 紧缩标题字体 + 系统无衬线体正文 |
| 文档 | 等宽代码 + 来自同一字族的无衬线体散文 | IBM Plex Mono + IBM Plex Sans |
| 极简品牌 | 单一字族,字重变化 | 不同字重和尺寸的Inter |
复制模式:
/* 经典衬线体 + 无衬线体配对 */
h1, h2, h3 {
font-family: 'Playfair Display', Georgia, serif;
}
body {
font-family: 'Source Sans Pro', -apple-system, sans-serif;
}
/* 超级字族配对 */
h1, h2, h3 {
font-family: 'Roboto Slab', serif;
}
body {
font-family: 'Roboto', sans-serif;
}
道德边界: 如有疑问,使用单一字族并变化字重,而不是强行配对。不匹配的配对会产生认知摩擦,破坏内容,而增加无目的的复杂性服务于设计师的自我,而非读者的需求。
参见:references/pairing-strategies.md 了解具体组合、对比方法和经过验证的配对。
核心理念: 三个测量值——字体大小、行长和行高——构成了舒适阅读的基础。正确设置这些比选择字体更重要。
为何有效: 这些测量值直接控制眼睛如何横向和纵向跟踪文本。最佳行长(45-75个字符)匹配扫视模式。足够的行高(1.4-1.8)防止眼睛在回扫时跳错行。足够的字体大小(最小16-18px)确保字形在屏幕上足够大,便于舒适识别。
关键见解:
ch单位或max-width来强制执行。更长的行需要更多的行高来补偿产品应用:
| 情境 | 应用 | 示例 |
|---|---|---|
| 博客 / 文章 | 强制执行65ch最大宽度,1.6行高 | .prose { max-width: 65ch; line-height: 1.6; } |
| 文档 | 稍宽的度量,增加行高 | max-width: 75ch; line-height: 1.7; |
| 移动端 UI | 更大的正文尺寸,自动约束的度量 | font-size: 17px; 配合视口宽度约束 |
| 仪表板 | 更紧的行高用于密集数据显示 | line-height: 1.3; 用于表格单元格和标签 |
| 落地页 | 慷慨的尺寸和间距以提高可扫描性 | font-size: 1.25rem; line-height: 1.7; |
| 电子邮件模板 | 约束宽度以适应电子邮件客户端兼容性 | max-width: 600px; 配合内联尺寸 |
复制模式:
/* 最佳正文测量值 */
.prose {
font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
line-height: 1.6;
max-width: 65ch;
}
/* 更宽的列需要更多的行高 */
.wide-text {
max-width: 80ch;
line-height: 1.8;
}
/* 根据情境调整行高 */
h1, h2 { line-height: 1.1-1.25; }
.ui-text { line-height: 1.3-1.4; }
.body-text { line-height: 1.5-1.7; }
道德边界: 切勿为了布局美学而牺牲可读的测量值。将文本挤入狭窄的列并使用微小尺寸以"适应设计",是将视觉排列置于人类理解之上。
参见:references/responsive-typography.md 了解流体尺寸和基于视口的测量策略。
核心理念: 层次结构告诉读者什么最重要。通过控制大小、字重和颜色的变化来创造区别——但不要同时使用所有杠杆。
为何有效: 视觉层次结构模仿了读者自然优先处理信息的方式。当层级之间的大小、字重和颜色差异是刻意且一致的时,读者可以扫描页面并立即理解其结构。没有层次结构,所有内容都争夺注意力,结果一无所获。
关键见解:
产品应用:
| 情境 | 应用 | 示例 |
|---|---|---|
| 内容页面 | 4-5个层级的大小 + 字重变化 | H1 2.5rem/700, H2 1.75rem/600, 正文 1rem/400 |
| 仪表板 | 数据与标签区别的字重 + 颜色 | 值:粗体 #111,标签:常规 #666 |
| 导航 | 大小 + 字重表示当前 vs 可用 | 激活:粗体,未激活:常规,相同大小 |
| 营销页面 | 大幅跳跃以实现戏剧性的可扫描性 | 主标题 3.5rem,节标题 2rem,正文 1.125rem |
| 表单 UI | 标签与输入区别的微妙字重变化 | 标签:600字重,输入:400字重 |
| 移动应用 | 由于视口有限,使用更紧的比例 | H1 1.75rem, H2 1.25rem, 正文 1rem |
复制模式:
/* 使用模块化比例的字体层次结构 */
h1 { font-size: clamp(2rem, 1.5rem + 2vw, 3rem); font-weight: 700; color: #111; }
h2 { font-size: clamp(1.5rem, 1.25rem + 1vw, 2rem); font-weight: 600; color: #111; }
h3 { font-size: 1.25rem; font-weight: 600; color: #333; }
body { font-size: 1rem; font-weight: 400; color: #333; }
.secondary { font-size: 0.875rem; color: #666; }
.caption { font-size: 0.75rem; color: #888; }
/* 标题节奏 */
h1, h2, h3 {
margin-top: 1.5em;
margin-bottom: 0.5em;
line-height: 1.2;
}
道德边界: 层次结构应诚实地引导读者。使用视觉突出性来吸引注意力到欺骗性元素(小文本中的隐藏费用,粗体中的操纵性CTA)是将排版武器化来对抗读者。
参见:references/css-implementation.md 了解完整的层次结构实现模式和可变字体技术。
核心理念: 字体必须适应屏幕和阅读情境,网页字体必须高效加载。使用clamp()的流体排版消除了断点跳跃,而策略性的字体加载防止布局偏移和缓慢渲染。
为何有效: 单一的固定字体大小无法同时服务于320px的手机和1440px的桌面。流体缩放确保文本始终与其视口成比例。同时,网页字体默认是渲染阻塞的——未优化的加载会导致不可见文本闪烁(FOIT)或无样式文本闪烁(FOUT),两者都会降低阅读体验。
关键见解:
clamp(min, preferred, max) 在视口尺寸之间平滑缩放字体大小,消除了为字体大小设置媒体查询断点的需要font-display: swap立即显示回退文本,使用<link rel="preload">预加载关键字体,并对字体进行子集化以仅包含所需字符产品应用:
| 情境 | 应用 | 示例 |
|---|---|---|
| 内容站点 | 使用clamp()的流体正文和标题尺寸 | font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem) |
| 电子商务 | 预加载主标题字体,懒加载次要字重 | <link rel="preload" href="font.woff2" as="font"> |
| SaaS应用 | UI使用系统字体栈,仅营销页面使用网页字体 | 应用中使用-apple-system,落地页使用自定义字体 |
| 全球产品 | 按语言子集化字体以减少负载 | 英语页面使用拉丁子集,亚洲页面使用CJK子集 |
| 性能关键 | 可变字体替换4-6个静态文件 | 单个可变字体文件,字重轴300-700 |
| 渐进式Web应用 | 在Service Worker中缓存字体以供离线使用 | caches.open('fonts').then(cache => cache.addAll(...)) |
复制模式:
/* 使用clamp()的流体排版 */
body {
font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
}
h1 {
font-size: clamp(2rem, 1.5rem + 2vw, 3.5rem);
}
/* 高性能字体加载 */
@font-face {
font-family: 'Custom Font';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap;
font-weight: 400;
unicode-range: U+0000-00FF; /* 拉丁子集 */
}
/* 在HTML头部预加载 */
/* <link rel="preload" href="/fonts/custom.woff2" as="font" type="font/woff2" crossorigin> */
道德边界: 性能优化不应以排除用户为代价。激进的子集化丢弃非英语读者所需的字符,或移除强调所需的斜体/粗体字重,是以伤害真实用户的方式用速度换取包容性。
参见:references/responsive-typography.md 了解流体类型实现,以及references/css-implementation.md 了解@font-face、加载策略和可变字体。
| 错误 | 为何失败 | 修复方法 |
|---|---|---|
| 文本感觉拥挤 | 行高不足造成视觉密度,使读者疲劳 | 增加行高至1.6+;添加段落间距 |
| 行太长,难以跟踪 | 超过75个字符,眼睛在回扫时迷失位置 | 为文本容器添加max-width: 65ch |
| 标题看起来脱节 | 标题上方空间过大,破坏了与后续内容的关联 | 减少标题上方空间;保持下方空间 |
| 文本在屏幕上看起来模糊 | 字体平滑设置不佳或子像素渲染问题 | 检查字体平滑;尝试不同字重;增加尺寸 |
| 字体加载缓慢 | 未优化的字体文件阻塞渲染并延迟首次内容绘制 | 子集化字体;使用font-display: swap;预加载关键字体 |
| 正文太小 | 用户拿手机的距离比假设的要远;小文本使年长眼睛疲劳 | 增加到18px;在真实距离下用真实用户测试 |
| 层次结构不清晰 | 相邻层级之间对比不足,使所有内容都竞争注意力 | 增加层级之间的大小/字重差异 |
| 字体冲突 | 配对字体没有清晰对比,产生无法解决的视觉紧张感 | 简化为单一字族;或确保结构对比(衬线体+无衬线体) |
| 使用Lorem ipsum进行测试 | 虚拟文本隐藏了字符频率、单词长度和节奏问题 | 使用代表实际使用的真实内容进行测试 |
| 问题 | 如果否 | 行动 |
|---|---|---|
| 正文字体是否16px或更大? | 文本太小,不适合舒适的屏幕阅读 | 增加到至少16px;对于阅读密集型页面,建议18px |
| 行长是否少于75个字符? | 眼睛在回扫时失去位置 | 为散文容器添加max-width: 65ch |
| 正文行高是否1.4或更高? | 行感觉拥挤,阅读速度下降 | 增加到1.5-1.7用于正文 |
| 字体层级之间是否有足够的对比? | 层次结构不可见;读者无法扫描 | 增加相邻层级之间的大小或字重差异 |
| 字体是否在实际尺寸和真实屏幕上测试过? | 生产环境会出现渲染意外 | 在目标设备和浏览器上测试每个使用尺寸 |
| 字体总负载是否低于200KB? | 加载缓慢会降低体验和SEO | 子集化字体,使用WOFF2,考虑可变字体 |
| 是否指定了回退字体? | FOIT在字体加载时留下空白文本 | 在每个font-family声明中添加系统字体回退 |
| 页面在200%浏览器缩放下是否正常工作? | 对低视力用户的无障碍性失败 | 在200%缩放下测试;修复溢出和截断问题 |
| 标题是否没有孤立的单个单词? | 单个尾随单词看起来未完成且浪费空间 | 使用text-wrap: balance或手动换行 |
| 链接是否与周围文本视觉上不同? | 用户无法识别交互元素 | 确保链接有颜色和/或下划线区别 |
On Web Typography 作者:Jason Santa Maria 出版社:A Book Apart (2014) ISBN:978-1937557065 Amazon
Jason Santa Maria 是一位平面设计师、创意总监和教育家,他的工作塑造了行业对网页排版的思考方式。他曾担任Typekit(现Adobe Fonts)的创意总监,帮助大规模地将高质量字体带给网页设计师。他共同创立了A Book Apart,这是一家为网站制作者出版简短书籍的出版社,并且一直是网页标准和设计教育领域的领军人物。Santa Maria在纽约市视觉艺术学院(SVA)任教,并曾担任包括A List Apart在内的出版物的艺术总监。他的工作弥合了传统排版工艺与屏幕设计实际现实之间的差距,而《On Web Typography》将他深厚的专业知识提炼成一份可供在职网页设计师使用的、易于理解且观点鲜明的指南。
每周安装次数
561
仓库
GitHub星标数
255
首次出现
2026年1月30日
安全审计
安装于
opencode519
gemini-cli510
codex507
github-copilot493
cursor482
kimi-cli479
A practical guide to choosing, pairing, and implementing typefaces for the web. Typography serves communication — the best typography is invisible, immersing readers in content rather than calling attention to itself.
Typography is the voice of your content. The typeface you choose sets tone before a single word is read. A legal site shouldn't feel playful; a children's app shouldn't feel corporate.
The "clear goblet" principle: Typography should be like a crystal-clear wine glass — the focus is on the wine (content), not the glass (type). Readers should absorb meaning, not notice letterforms.
Readers don't read, they scan. Eyes jump 7-9 characters at a time (saccades), pausing briefly (fixations). Good typography supports this natural pattern.
Goal: 10/10. When reviewing or creating typography implementations, rate them 0-10 based on adherence to the principles below. A 10/10 means full alignment with all guidelines; lower scores indicate gaps to address. Always provide the current score and specific improvements needed to reach 10/10.
All typography falls into two categories:
| Context | Purpose | Priorities |
|---|---|---|
| Type for a moment | Headlines, buttons, navigation, logos | Personality, impact, distinctiveness |
| Type to live with | Body text, articles, documentation | Readability, comfort, endurance |
Workhorse typefaces excel at "type to live with" — they're versatile across sizes, weights, and contexts without drawing attention to themselves. Examples: Georgia, Source Sans, Freight Text, FF Meta.
Core concept: Understanding reading mechanics is the foundation for every typography decision. Eyes don't scan smoothly — they jump in bursts, and good typography supports this natural pattern.
Why it works: When typography aligns with how the brain processes text — through word shape recognition, consistent rhythm, and clear letterform distinction — readers absorb content faster with less fatigue. Fighting these mechanics creates friction that drives readers away.
Key insights:
Product applications:
| Context | Application | Example |
|---|---|---|
| Long-form content | Optimize for sustained reading comfort | 16-18px body text, 1.5-1.7 line height, 45-75 char lines |
| Dashboard UI | Optimize for rapid scanning | Distinct weight hierarchy, ample whitespace between data groups |
| Mobile reading | Account for variable distance and lighting | Slightly larger body size (17-18px), higher contrast |
| Documentation | Support both scanning and deep reading | Clear heading hierarchy with generous paragraph spacing |
| E-commerce | Enable quick product comparison | Consistent number formatting, tabular figures |
| Accessibility | Support readers with varying abilities | High contrast, generous spacing, distinct letterforms |
Copy patterns:
/* Optimal reading rhythm for body text */
.prose {
font-size: 1.125rem; /* 18px */
line-height: 1.6;
max-width: 65ch; /* ~45-75 characters */
letter-spacing: normal; /* Don't force tracking on body text */
}
Ethical boundary: Typography decisions should always prioritize reader comprehension and comfort over visual novelty. Sacrificing readability for aesthetic effect excludes readers and undermines the content's purpose.
See: references/typeface-anatomy.md for terminology, letterform parts, and classification systems.
Core concept: A typeface must pass technical, structural, and practical quality checks before it earns a place in a project. Beautiful specimens fail on screen; rigorous evaluation prevents costly mid-project typeface swaps.
Why it works: Screen rendering, variable bandwidth, and diverse devices impose constraints that print never faced. A typeface that passes structural assessment (consistent strokes, open counters, distinct letterforms) and practical assessment (file size, license, rendering) will perform reliably across the full range of real-world conditions.
Key insights:
Product applications:
| Context | Application | Example |
|---|---|---|
| Body text selection | Prioritize x-height, open counters, even color | Source Serif Pro over Didot for long reads |
| Headline selection | Prioritize personality and distinctiveness at large sizes | Playfair Display for editorial impact |
| UI/System text | Prioritize legibility at small sizes and weight range | Inter or SF Pro for interface elements |
| Multilingual product | Verify complete glyph coverage for target languages | Noto Sans for broad Unicode support |
| Performance-critical site | Evaluate file size and subsetting options | Variable font single file vs. multiple static weights |
| Brand refresh | Assess whether typeface conveys intended personality | Compare specimen at actual use sizes against brand attributes |
Copy patterns:
/* Test typeface at actual use sizes */
body { font-size: 16px; } /* Minimum body size */
.caption { font-size: 0.75rem; } /* Stress-test small sizes */
h1 { font-size: 3rem; } /* Check large-size character */
/* Verify rendering with font-smoothing */
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
Ethical boundary: Always verify typeface licensing before implementation. Using unlicensed fonts exposes projects to legal risk and undermines the type design community that creates these tools.
See: references/evaluating-typefaces.md for detailed quality assessment criteria and structural analysis.
Core concept: Start with purpose, not aesthetics. The content's tone, reading context, duration, and personality should drive typeface selection — not personal preference or trend following.
Why it works: When typeface selection is grounded in content requirements, the result feels inevitable rather than arbitrary. Purpose-driven choices also survive stakeholder review better because they can be justified with clear reasoning rather than subjective taste.
Key insights:
Product applications:
| Context | Application | Example |
|---|---|---|
| Content-heavy site | Select a workhorse serif or sans for sustained reading | Source Serif Pro or Charter for articles |
| SaaS dashboard | Choose a clean sans with strong tabular figures | Inter or IBM Plex Sans for data-rich interfaces |
| Marketing landing page | Pair a distinctive display face with a readable body face | Playfair Display headlines + Source Sans Pro body |
| Documentation site | Prioritize clarity and weight range for code + prose | IBM Plex Mono for code, IBM Plex Sans for prose |
| Brand-driven product | Commission or license a face that embodies brand values | Custom typeface or carefully chosen match to brand personality |
| Accessibility-focused | Select faces designed for maximum legibility | Atkinson Hyperlegible for vision-impaired users |
Copy patterns:
/* Safe system font stack */
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI',
Roboto, Oxygen, Ubuntu, sans-serif;
}
/* Reliable web font body stack */
body {
font-family: 'Source Sans Pro', -apple-system,
BlinkMacSystemFont, sans-serif;
}
Ethical boundary: Avoid choosing typefaces solely to appear trendy or sophisticated at the expense of readability. Typography that excludes readers with lower vision or reading difficulties in favor of visual style fails its fundamental purpose.
See: references/evaluating-typefaces.md for quality assessment to apply during selection.
Core concept: Successful typeface pairings create clear contrast — faces should be obviously different, not confusingly similar. One to two typefaces maximum; more requires exceptional skill.
Why it works: Contrast between typefaces creates visual hierarchy and rhythm. When two faces are too similar, they create tension without purpose — the reader senses something is "off" without knowing why. Clear structural contrast (serif + sans, light + bold, humanist + geometric) lets each face play a distinct role while coexisting harmoniously.
Key insights:
Product applications:
| Context | Application | Example |
|---|---|---|
| Editorial site | Serif headlines + sans body for classic readability | Playfair Display + Source Sans Pro |
| Tech product | Superfamily for guaranteed harmony | Roboto + Roboto Slab |
| Corporate site | Same-designer pairing for subtle cohesion | FF Meta + FF Meta Serif |
| E-commerce | Distinctive display + neutral body | Condensed headline face + system sans-serif body |
| Documentation | Monospace code + sans-serif prose from same family | IBM Plex Mono + IBM Plex Sans |
| Minimal brand | Single family with weight variation | Inter at varying weights and sizes |
Copy patterns:
/* Classic serif + sans-serif pairing */
h1, h2, h3 {
font-family: 'Playfair Display', Georgia, serif;
}
body {
font-family: 'Source Sans Pro', -apple-system, sans-serif;
}
/* Superfamily pairing */
h1, h2, h3 {
font-family: 'Roboto Slab', serif;
}
body {
font-family: 'Roboto', sans-serif;
}
Ethical boundary: When in doubt, use one family with weight variation rather than forcing a pairing. A mismatched pairing creates cognitive friction that undermines the content, and adding complexity without purpose serves the designer's ego rather than the reader's needs.
See: references/pairing-strategies.md for specific combinations, contrast methods, and proven pairings.
Core concept: Three measurements — font size, line length, and line height — form the foundation of comfortable reading. Getting these right matters more than typeface choice.
Why it works: These measurements directly govern how the eye tracks across and down text. Optimal line length (45-75 characters) matches the saccade pattern. Adequate line height (1.4-1.8) prevents the eye from jumping to the wrong line on the return sweep. Sufficient font size (16-18px minimum) ensures letterforms are large enough for comfortable recognition on screen.
Key insights:
ch unit or max-width to enforce. Longer lines need more line height to compensateProduct applications:
| Context | Application | Example |
|---|---|---|
| Blog / article | Enforce 65ch max-width with 1.6 line height | .prose { max-width: 65ch; line-height: 1.6; } |
| Documentation | Slightly wider measure with increased line height | max-width: 75ch; line-height: 1.7; |
| Mobile UI | Larger body size, auto-constrained measure | font-size: 17px; with viewport-width constraint |
| Dashboard | Tighter line height for dense data display | line-height: 1.3; for table cells and labels |
| Landing page | Generous sizing and spacing for scanability |
Copy patterns:
/* Optimal body text measurements */
.prose {
font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
line-height: 1.6;
max-width: 65ch;
}
/* Wider columns need more line height */
.wide-text {
max-width: 80ch;
line-height: 1.8;
}
/* Line height adjustments by context */
h1, h2 { line-height: 1.1-1.25; }
.ui-text { line-height: 1.3-1.4; }
.body-text { line-height: 1.5-1.7; }
Ethical boundary: Never sacrifice readable measurements for layout aesthetics. Cramming text into narrow columns with tiny sizes to "fit the design" prioritizes visual arrangement over human comprehension.
See: references/responsive-typography.md for fluid sizing and viewport-based measurement strategies.
Core concept: Hierarchy tells readers what matters most. Create distinction through controlled variation in size, weight, and color — but don't combine all levers at once.
Why it works: Visual hierarchy mimics how readers naturally prioritize information. When size, weight, and color differences between levels are deliberate and consistent, readers can scan a page and instantly understand its structure. Without hierarchy, everything competes for attention and nothing wins.
Key insights:
Product applications:
| Context | Application | Example |
|---|---|---|
| Content page | Size + weight variation across 4-5 levels | H1 2.5rem/700, H2 1.75rem/600, Body 1rem/400 |
| Dashboard | Weight + color for data vs. label distinction | Bold #111 for values, Regular #666 for labels |
| Navigation | Size + weight to signal current vs. available | Active: bold, Inactive: regular, same size |
| Marketing page | Large size jumps for dramatic scanability | Hero 3.5rem, Section heads 2rem, Body 1.125rem |
| Form UI | Subtle weight shifts for label vs. input distinction | Label: 600 weight, Input: 400 weight |
| Mobile app | Tighter scale due to limited viewport | H1 1.75rem, H2 1.25rem, Body 1rem |
Copy patterns:
/* Type hierarchy with modular scale */
h1 { font-size: clamp(2rem, 1.5rem + 2vw, 3rem); font-weight: 700; color: #111; }
h2 { font-size: clamp(1.5rem, 1.25rem + 1vw, 2rem); font-weight: 600; color: #111; }
h3 { font-size: 1.25rem; font-weight: 600; color: #333; }
body { font-size: 1rem; font-weight: 400; color: #333; }
.secondary { font-size: 0.875rem; color: #666; }
.caption { font-size: 0.75rem; color: #888; }
/* Heading rhythm */
h1, h2, h3 {
margin-top: 1.5em;
margin-bottom: 0.5em;
line-height: 1.2;
}
Ethical boundary: Hierarchy should guide readers honestly. Using visual prominence to draw attention to deceptive elements (hidden fees in small text, manipulative CTAs in bold) weaponizes typography against the reader.
See: references/css-implementation.md for complete hierarchy implementation patterns and variable font techniques.
Core concept: Type must adapt to screens and reading contexts, and web fonts must load efficiently. Fluid typography with clamp() eliminates breakpoint jumps, while strategic font loading prevents layout shift and slow renders.
Why it works: A single fixed font size cannot serve both a 320px phone and a 1440px desktop. Fluid scaling ensures text is always proportionate to its viewport. Meanwhile, web fonts are render-blocking by default — unoptimized loading causes Flash of Invisible Text (FOIT) or Flash of Unstyled Text (FOUT), both of which degrade the reading experience.
Key insights:
clamp(min, preferred, max) scales font size smoothly between viewport sizes, eliminating the need for media query breakpoints for type sizingfont-display: swap to show fallback text immediately, preload critical fonts with <link rel="preload">, and subset fonts to include only needed charactersProduct applications:
| Context | Application | Example |
|---|---|---|
| Content site | Fluid body and heading sizes with clamp() | font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem) |
| E-commerce | Preload hero font, lazy-load secondary weights | <link rel="preload" href="font.woff2" as="font"> |
| SaaS app | System font stack for UI, web font for marketing only | -apple-system in app, custom font on landing page |
| Global product | Subset fonts per language to reduce payload | Latin subset for English pages, CJK subset for Asian pages |
| Performance-critical | Variable font replacing 4-6 static files | Single variable font file with weight axis 300-700 |
| Progressive web app |
Copy patterns:
/* Fluid typography with clamp() */
body {
font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
}
h1 {
font-size: clamp(2rem, 1.5rem + 2vw, 3.5rem);
}
/* Performant font loading */
@font-face {
font-family: 'Custom Font';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap;
font-weight: 400;
unicode-range: U+0000-00FF; /* Latin subset */
}
/* Preload in HTML head */
/* <link rel="preload" href="/fonts/custom.woff2" as="font" type="font/woff2" crossorigin> */
Ethical boundary: Performance optimization should not come at the cost of excluding users. Aggressive subsetting that drops characters needed by non-English readers, or removing italic/bold weights needed for emphasis, trades inclusivity for speed in ways that harm real people.
See: references/responsive-typography.md for fluid type implementation and references/css-implementation.md for @font-face, loading strategies, and variable fonts.
| Mistake | Why It Fails | Fix |
|---|---|---|
| Text feels cramped | Insufficient line height creates visual density that fatigues readers | Increase line-height to 1.6+; add paragraph spacing |
| Lines too long, hard to track | Beyond 75 characters, the eye loses its place on the return sweep | Add max-width: 65ch to text containers |
| Headings look disconnected | Excessive space above headings breaks their association with following content | Reduce space above heading; keep space below |
| Text looks blurry on screen | Poor font-smoothing settings or subpixel rendering issues | Check font-smoothing; try different weight; increase size |
| Fonts loading slowly | Unoptimized font files block rendering and delay first contentful paint | Subset fonts; use font-display: swap; preload critical fonts |
| Body text too small | Users hold phones farther than assumed; small text strains older eyes |
| Question | If No | Action |
|---|---|---|
| Is body text 16px or larger? | Text too small for comfortable screen reading | Increase to at least 16px; prefer 18px for reading-heavy pages |
| Is line length under 75 characters? | Eye loses position on return sweep | Add max-width: 65ch to prose containers |
| Is line height 1.4 or greater for body? | Lines feel cramped and reading speed drops | Increase to 1.5-1.7 for body text |
| Is there sufficient contrast between type levels? | Hierarchy is invisible; readers can't scan | Increase size or weight differences between adjacent levels |
| Have typefaces been tested at actual sizes on real screens? | Rendering surprises will appear in production | Test at every use size on target devices and browsers |
| Is total font payload under 200KB? | Slow loading degrades experience and SEO | Subset fonts, use WOFF2, consider variable fonts |
| Are fallback fonts specified? | FOIT leaves blank text while fonts load |
On Web Typography by Jason Santa Maria Publisher: A Book Apart (2014) ISBN: 978-1937557065 Amazon
Jason Santa Maria is a graphic designer, creative director, and educator whose work has shaped how the industry thinks about typography on the web. He served as Creative Director at Typekit (now Adobe Fonts), where he helped bring high-quality type to web designers at scale. He co-founded A Book Apart, the publisher of brief books for people who make websites, and has been a leading voice in web standards and design education. Santa Maria teaches at the School of Visual Arts (SVA) in New York City and has art-directed publications including A List Apart. His work bridges the gap between traditional typographic craft and the practical realities of designing for screens, and "On Web Typography" distills his deep expertise into an accessible, opinionated guide for working web designers.
Weekly Installs
561
Repository
GitHub Stars
255
First Seen
Jan 30, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode519
gemini-cli510
codex507
github-copilot493
cursor482
kimi-cli479
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
106,200 周安装
飞书自动化工具 - 多维表格、消息、文档、群组、知识库、日历任务全通道自动化
264 周安装
阿里云通义翻译AnyTrans API管理技能 - 快速调用SDK与OpenAPI Explorer指南
264 周安装
Lark Drive API 使用指南:飞书云文档、Wiki、表格 Token 处理与文件管理
15,400 周安装
LarkSuite Whiteboard CLI 工具:自动化生成专业图表与画板,支持DSL和Mermaid
15,500 周安装
UI/UX原型提示词生成器 - 为AI和开发者创建结构化设计规范
264 周安装
SEO优化器 | 关键词研究、页面优化、技术审计、排名跟踪一站式解决方案
264 周安装
font-size: 1.25rem; line-height: 1.7; |
| Email template | Constrained width for email client compatibility | max-width: 600px; with inline sizing |
| Cache fonts in service worker for offline use |
caches.open('fonts').then(cache => cache.addAll(...)) |
| Increase to 18px; test with real users at real distance |
| Hierarchy is unclear | Insufficient contrast between adjacent levels makes everything compete | Increase size/weight differences between levels |
| Typefaces clash | Pairing faces without clear contrast creates unresolvable visual tension | Simplify to one family; or ensure structural contrast (serif + sans) |
| Using Lorem ipsum for testing | Dummy text hides character frequency, word length, and rhythm problems | Test with real content representative of actual use |
| Add system font fallbacks in every font-family declaration |
| Does the page work at 200% browser zoom? | Accessibility failure for low-vision users | Test at 200% zoom; fix overflow and truncation issues |
| Are headings free of orphaned single words? | Single trailing words look unfinished and waste space | Use text-wrap: balance or manual breaks |
| Are links visually distinct from surrounding text? | Users cannot identify interactive elements | Ensure links have color and/or underline distinction |