关于 typography
为网页项目提供系统化排版指导,面向设计和开发工作。内容涵盖字体搭配、比例字号、响应式文字与字体加载策略。
主要功能
- 01选择模块化字号比例
- 02提供字体搭配建议
- 03规范标题与正文排版
- 04使用 clamp() 实现响应式字号
- 05指导字体加载与授权
适用场景
- 01为新网页建立排版系统
- 02优化长篇内容的可读性
- 03为移动端与桌面端设计流式字号
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ arnavpuri/ designskills --skill typography安装后在 Claude Code 中输入/typography确认已加载。
详细介绍
Typography Mastery
为任何 Web 项目打造美观、易读且系统化的排版。
前置条件
设置排版前,请检查现有的设计上下文:
- 阅读
.agents/design-context.md(参见design-context):标题/正文/等宽字体、基础字号、比例系数、标题/正文字重。除非用户明确要求更改,否则请沿用这些设置。 - 如果代码库中已有设计系统,请与其字号比例和字体栈保持一致。
- 注意:设计上下文中的“Type Scale Reference”(12/14/16/18/20/24/30/36/48/60/72)是 Tailwind 经过手动调整的字号比例,并非严格的 1.25 递进。如果项目已在使用该比例,请保留;如果是新工作,请根据已保存的比例系数(步骤 1)生成真正的模块化比例,并说明使用的是哪一种。
步骤 1:选择字号比例系数
字号比例系数决定字号之间的数学关系。请根据项目的内容密度和视觉风格进行选择。
| 比例名称 | 昵称 | 数值 | 最适用场景 |
|---|---|---|---|
| 小二度 | 紧凑 | 1.067 | 密集数据 UI、仪表板 |
| 大二度 | 紧凑型 | 1.125 | 应用、工具、紧凑布局 |
| 小三度 | 默认 | 1.200 | 常规 Web、博客、营销 |
| 大三度 | 舒展 | 1.250 | 编辑类内容、杂志 |
| 完全四度 | 醒目 | 1.333 | 营销网站、着陆页 |
| 增四度 | 冲击 | 1.414 | 醒目的标题、创意网站 |
| 完全五度 | 戏剧感 | 1.500 | 高冲击力的主视觉区块 |
| 黄金比例 | 宏大 | 1.618 | 艺术、奢华、编辑类内容 |
生成字号比例
:root {
--type-ratio: 1.25; /* major third */
--type-base: 1rem; /* 16px */
/* Each step = previous * ratio, so changing --type-ratio updates the whole scale */
--text-xs: max(0.75rem, calc(var(--text-sm) / var(--type-ratio))); /* 0.64rem = 10.24px -> floored to 12px */
--text-sm: calc(var(--type-base) / var(--type-ratio)); /* 0.8rem = 12.8px */
--text-base: var(--type-base); /* 1rem = 16px */
--text-lg: calc(var(--text-base) * var(--type-ratio)); /* 1.25rem = 20px */
--text-xl: calc(var(--text-lg) * var(--type-ratio)); /* 1.563rem = 25px */
--text-2xl: calc(var(--text-xl) * var(--type-ratio)); /* 1.953rem = 31.25px */
--text-3xl: calc(var(--text-2xl) * var(--type-ratio)); /* 2.441rem = 39px */
--text-4xl: calc(var(--text-3xl) * var(--type-ratio)); /* 3.052rem = 48.8px */
--text-5xl: calc(var(--text-4xl) * var(--type-ratio)); /* 3.815rem = 61px */
}
公式:size(n) = base × ratio^n。上方注释针对比例系数 1.25;如果更改比例系数,请重新计算。功能性文本(说明文字、标签)请保持 12px 或更大。
步骤 2:字体搭配规则
核心搭配策略
- 衬线标题 + 无衬线正文:经典的编辑风格,结构对比鲜明。
- 几何无衬线标题 + 人文主义无衬线正文:现代而温暖。
- 粗衬线标题 + 无衬线正文:醒目、自信。
- 等宽标题 + 无衬线正文:技术感强,面向开发者。
- 同一字体家族,不同字重:最稳妥的选择。标题使用 700+,正文使用 400。
应避免的情况
- 使用两种来自同一类别且比例相似的字体(例如,两种几何无衬线字体)。
- 单个页面使用超过 2 种字体(如果其中一种是用于代码的等宽字体,最多可用 3 种)。
- 正文使用装饰字体或展示字体。
步骤 3:精选 Google Fonts 字体搭配
以下搭配均经过测试,可用于生产环境。
编辑类 / 内容密集型
-
Playfair Display + Source Sans 3 优雅的衬线标题,搭配简洁的无衬线正文。适合杂志、博客。
-
Lora + Inter 温暖的过渡型衬线字体 + 中性的现代无衬线字体。可读性出色。
-
Fraunces + Commissioner 富有个性的可变“柔和”衬线字体 + 低对比度的人文主义无衬线字体。编辑风格鲜明。
现代 / SaaS
-
Inter + Inter 单字体家族方案。标题使用 700,正文使用 400。适用性极强。
-
DM Sans + DM Sans 几何风格、现代感强。比 Inter 略具个性。
-
Manrope + Source Sans 3 半窄体几何无衬线字体 + 人文主义无衬线字体。呈现友好的科技感。
醒目 / 营销
-
Space Grotesk + General Sans(Fontshare,可自托管)或 Space Grotesk + DM Sans 带有等宽字体风格的无衬线字体 + 简洁的几何字体。科技感强且醒目。
-
Bricolage Grotesque + Inter 用于标题的俏皮可变无衬线字体 + 可靠的正文字体。活泼而专业。
-
Cabinet Grotesk + Satoshi(均来自 Fontshare,可自托管——参见 Licensing) 现代几何字体搭配。呈现高端初创公司的美学风格。
专用字体组合
-
JetBrains Mono + Inter 等宽字体标题/代码 + 无衬线正文字体。适用于开发者工具和文档。
-
Instrument Serif + Instrument Sans 配套设计的衬线/无衬线组合。低风险搭配(Instrument Serif 仅适用于展示字体——用于标题,不用于正文)。
-
Sora + Newsreader 几何风格无衬线标题 + 易读的衬线正文字体。经典搭配的反转。
CSS 导入模式
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:wght@700;800&display=swap" rel="stylesheet">
:root {
--font-heading: 'Playfair Display', Georgia, serif;
--font-body: 'Inter', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
}
第 4 步:标题层级
推荐默认值(1.25 比率,基准 16px)
h1 {
font-family: var(--font-heading);
font-size: var(--text-5xl); /* ~3.8rem / 61px */
font-weight: 800;
line-height: 1.1;
letter-spacing: -0.025em;
margin-bottom: 0.5em;
}
h2 {
font-family: var(--font-heading);
font-size: var(--text-4xl); /* ~3.05rem / 49px */
font-weight: 700;
line-height: 1.15;
letter-spacing: -0.02em;
margin-bottom: 0.5em;
}
h3 {
font-family: var(--font-heading);
font-size: var(--text-3xl); /* ~2.44rem / 39px */
font-weight: 700;
line-height: 1.2;
letter-spacing: -0.015em;
margin-bottom: 0.5em;
}
h4 {
font-size: var(--text-2xl); /* ~1.95rem / 31px */
font-weight: 600;
line-height: 1.25;
letter-spacing: -0.01em;
}
h5 {
font-size: var(--text-xl); /* ~1.56rem / 25px */
font-weight: 600;
line-height: 1.3;
}
h6 {
font-size: var(--text-lg); /* ~1.25rem / 20px */
font-weight: 600;
line-height: 1.4;
text-transform: uppercase;
letter-spacing: 0.05em;
}
关键规则
- 大号标题使用负字间距(-0.01em 至 -0.03em)。
- 标题的行高应比正文字体更紧凑(1.1-1.3)。
- 切勿为了使用更小字号而跳过标题级别(h1 -> h3)。标题级别是供屏幕阅读器使用的文档结构;可通过类名调整外观(
<h2 class="h4">)。
第 5 步:优化正文字体
黄金法则
- 字号:至少 16px,长篇内容建议使用 18px。
- 行高:UI 使用 1.5,长篇阅读使用 1.6-1.75。
- 行长:每行 45-75 个字符(65ch 为理想值)。
- 段落间距:段落之间间隔 1em-1.5em。
body {
font-family: var(--font-body);
font-size: 1.125rem; /* 18px */
line-height: 1.65;
color: var(--text-primary, var(--gray-900)); /* design-context: Neutral 800 body / 900 headings */
-webkit-font-smoothing: antialiased; /* macOS only; harmless elsewhere */
text-rendering: optimizeLegibility;
}
.prose {
max-width: 65ch;
margin-inline: auto;
}
.prose p + p {
margin-top: 1.25em;
}
.prose > * + * {
margin-top: 1em;
}
第 6 步:使用 clamp() 实现响应式排版
使用 clamp() 在断点之间流畅缩放,无需媒体查询。
公式
clamp(min, preferred, max)
slope = (maxSize - minSize) / (maxViewport - minViewport) e.g. (24 - 20) / (1280 - 360) = 0.004348
preferred = (slope * 100)vw + (minSize - slope * minViewport)/16 rem
= 0.4348vw + 1.152rem -> clamp(1.25rem, 0.4348vw + 1.152rem, 1.5rem)
首选值中始终保留 rem 项:纯 vw 尺寸不会随浏览器缩放而增大,且不符合 WCAG 1.4.4(调整文本大小)要求。
实用的流体字号比例
这会替换第 1 步中的静态比例(两者择一使用,不要同时使用)。最大值在桌面视口宽度下约按 1.25-1.33 的比例递增;最小值则接近移动端静态比例。
:root {
--text-base: clamp(1rem, 0.5vw + 0.875rem, 1.125rem);
--text-lg: clamp(1.125rem, 0.75vw + 0.9rem, 1.35rem);
--text-xl: clamp(1.25rem, 1vw + 0.95rem, 1.75rem);
--text-2xl: clamp(1.5rem, 1.5vw + 1rem, 2.25rem);
--text-3xl: clamp(1.875rem, 2vw + 1.1rem, 3rem);
--text-4xl: clamp(2.25rem, 3vw + 1rem, 4rem);
--text-5xl: clamp(2.75rem, 4vw + 1rem, 5.5rem);
}
主视觉标题模式
.hero-title {
font-size: clamp(2.5rem, 5vw + 1rem, 6rem);
font-weight: 800;
line-height: 1.05;
letter-spacing: -0.03em;
text-wrap: balance; /* evens out line lengths in short headings */
}
第 7 步:文本处理与效果
渐变文本
.gradient-text {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
描边/轮廓文本
.outlined-text {
-webkit-text-stroke: 2px currentColor;
-webkit-text-fill-color: transparent;
font-weight: 800;
font-size: 5rem;
}
文本阴影与叠加在图像上的文本
.text-shadow-soft { text-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.text-shadow-hard { text-shadow: 3px 3px 0 rgba(0,0,0,0.15); }
.text-over-image { text-shadow: 0 2px 16px rgba(0,0,0,0.5); } /* or a backdrop: */
.text-backdrop { background: rgba(0,0,0,0.5); backdrop-filter: blur(4px); padding: 0.5em 1em; border-radius: 0.25em; }
渐变、描边和带背景图像的文本仍须满足对比度要求:测量文本背后渐变/照片中最亮部分的亮度,并且描边文本仅用于展示字号。
第 8 步:可变字体
常见轴
| 轴 | CSS 属性 | 范围(典型值) |
|---|---|---|
| wght | font-weight | 100-900 |
| wdth | font-stretch | 75%-125% |
| slnt | font-style: oblique Xdeg | -12 至 0(因字体而异) |
| ital | font-style: italic | 0 或 1 |
| opsz | font-optical-sizing: auto | 范围不定(Inter 为 14-32) |
@font-face {
font-family: 'Inter Variable';
src: url('/fonts/InterVariable.woff2') format('woff2');
font-weight: 100 900;
font-display: swap;
}
.heading {
font-family: 'Inter Variable', sans-serif;
font-weight: 750; /* precise weight */
font-optical-sizing: auto; /* uses Inter's opsz axis automatically */
}
/* Width only works if the font HAS a wdth axis (e.g. Roboto Flex, Mona Sans; Inter has none) */
.heading-wide { font-stretch: 110%; }
优先使用高级属性(font-weight、font-stretch、font-style、font-optical-sizing),而非 font-variation-settings;后者会一次性覆盖所有轴,且不会按轴继承。使用前,请在字体的 Google Fonts 页面查看其轴。
第 9 步:字间距和词间距指南
| 场景 | 字间距 | 原因 |
|---|---|---|
| 大号标题(3rem+) | -0.02 至 -0.03em | 收紧字距,增强视觉密度 |
| 小号标题 | -0.01em | 略微收紧 |
| 正文 | normal (0) | 默认值已优化 |
| 全大写文本 | +0.05 至 +0.1em | 大写字母需要更多呼吸空间 |
| 小号文本/说明文字 | +0.01 至 +0.02em | 提高小字号下的易读性 |
| 等宽字体 | normal | 字距已均匀 |
.caps-label {
text-transform: uppercase;
letter-spacing: 0.08em;
font-size: var(--text-sm);
font-weight: 600;
}
第 10 步:字体加载策略
推荐方式
二选一:Google Fonts CDN(选项 A)或自托管(选项 B,性能和隐私/GDPR 表现更佳)。
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preload" as="font" type="font/woff2"
href="/fonts/inter-var.woff2" crossorigin>
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-var.woff2') format('woff2');
font-weight: 100 900;
font-display: swap; /* Show fallback immediately, swap when loaded */
}
font-display 值
| 值 | 行为 | 适用场景 |
|---|---|---|
| swap | 立即显示后备字体,随后切换 | 正文,大多数情况 |
| optional | 短暂阻塞,可能跳过自定义字体 | 非关键装饰字体 |
| fallback | 短暂阻塞,切换时间较短 | 兼顾切换与 optional |
| block | 最长 3 秒内隐藏文本 | 仅适用于图标字体 |
系统字体栈后备方案
:root {
--font-system: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
}
避免布局偏移
使用 size-adjust、ascent-override 和 descent-override 来匹配后备字体的度量值:
@font-face {
font-family: 'Inter Fallback';
src: local('Arial');
size-adjust: 107%;
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
}
body { font-family: 'Inter', 'Inter Fallback', sans-serif; }
这些覆盖值适用于 Inter 搭配 Arial;其他字体请生成相应的值(例如使用 Fontaine、Capsize 或 next/font,后者会自动处理)。
许可
- Google Fonts 字体系列均为开源字体(几乎全部采用 SIL OFL 1.1,少数采用 Apache 2.0):可免费用于商业用途、嵌入和自托管。
- Fontshare 字体(Satoshi、General Sans、Cabinet Grotesk)根据 ITF Free Font License 免费用于商业用途,但不在 Google Fonts 中;请下载并自托管。
- 商业字体厂商的字体需要网页许可(通常按页面浏览量定价)。未经许可确认,切勿自托管从设计工具或操作系统中提取的字体文件。
快速参考清单
- 选择适合项目的字体比例。
- 最多选择 2 种字体(如果包含等宽字体,则可选 3 种)。
- 将正文字号设为 16-18px,行高设为 1.5-1.75。
- 将行长限制在 45-75 个字符。
- 使用
clamp()实现流畅的响应式字号。 - 为大号标题设置负字间距。
- 为大写文本设置正字间距。
- 预加载关键字体;使用
font-display: swap。 - 设置系统字体后备栈。
- 在标题上使用
text-wrap: balance,在段落上使用text-wrap: pretty,以避免孤行。
验证并保存
- 渲染字体样张:编写一个 HTML 页面(临时页面),使用实际字体展示 h1-h6、正文段落(实际宽度下约 3 行)、说明文字、标签、代码以及一行很长且不换行的标题。在 375px 和 1280px 宽度下截图(
npx playwright screenshot --viewport-size=375,800 --full-page "file://$PWD/specimen.html" mobile.png),并使用 Read 查看两张截图。检查:字体已实际加载(而非后备字体)、各级字号之间的层次清晰、正文行长为 45-75 个字符、标题宽度没有超出视口。 - 提出回写选项:更新
.agents/design-context.md中已变更的 Typography 字段(Heading Font、Body Font、Mono Font、Base Size、Scale Ratio、Heading Weight、Body Weight),并将其设为完整字体栈。展示差异并在保存前征求确认。