modular-scale-typography

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Modular Scale Typography

Modular Scale 排版

Typography feels cohesive when all font sizes are related to each other through a single mathematical ratio. Without a scale, sizes get picked arbitrarily and the result feels visually noisy — headings that don't contrast enough, body text too close in size to captions, labels that blend into content.
当所有字体大小通过单一数学比例相互关联时,排版会显得连贯统一。如果没有比例规范,字体大小的选择会变得随意,最终导致视觉杂乱——标题对比度不足、正文字号与说明文字过于接近、标签与内容混为一体。

What Is a Modular Scale

什么是Modular Scale

A modular scale starts from a base size and multiplies or divides by a ratio to generate every size in the system.
size(n) = base × ratio^n
Every size is thus a deliberate step away from the base — not a guess.
Modular Scale从一个基础尺寸出发,通过乘以或除以一个比例值来生成系统中的所有字体尺寸。
size(n) = base × ratio^n
每个尺寸都是与基础尺寸刻意拉开的差距,而非凭空猜测。

Choosing a Ratio

选择比例值

RatioNameFeelGood for
1.067Minor SecondVery tightDense data UIs, dashboards
1.125Major SecondSubtleLong-form reading, editorial
1.200Minor ThirdBalancedMost UI applications
1.250Major ThirdClear hierarchyMarketing, landing pages
1.333Perfect FourthStrong contrastDisplay, hero sections
1.414Augmented FourthDramaticPortfolios, branding
1.500Perfect FifthVery dramaticUse sparingly
Default recommendation:
1.25
(Major Third) — enough contrast between steps to feel intentional without being theatrical.
Ratio名称视觉感受适用场景
1.067Minor Second非常紧凑高密度数据UI、仪表盘
1.125Major Second细微柔和长篇阅读内容、编辑类页面
1.200Minor Third平衡适中大多数UI应用
1.250Major Third层级清晰营销页面、着陆页
1.333Perfect Fourth对比强烈展示区、Hero板块
1.414Augmented Fourth极具戏剧性作品集、品牌页面
1.500Perfect Fifth夸张醒目谨慎使用
默认推荐:
1.25
(Major Third)——各层级间的对比度足够,既显得有目的性又不会过于夸张。

Generating a Scale

生成字体比例

Recover an existing scale, don't reverse-engineer it by hand (dembrandt engine, optional). If a brand already has type on the web,
get_typography
returns the real font sizes, weights, and line-heights computed off the live DOM — infer the underlying ratio from those, then regularise it with the method below, instead of guessing which sizes were intended. See
extract-design
.
Starting from
base = 16px
, ratio
1.25
:
StepFormulaValueRoundedRole
-216 ÷ 1.25²10.24px10pxCaption, label-xs
-116 ÷ 1.2512.80px13pxLabel, small
01616px16pxBody (base)
+116 × 1.2520px20pxBody-lg, lead
+216 × 1.25²25px25pxH4
+316 × 1.25³31.25px31pxH3
+416 × 1.25⁴39.06px39pxH2
+516 × 1.25⁵48.83px49pxH1
+616 × 1.25⁶61.04px61pxDisplay
Round to whole pixels or rem — the ratio provides the intent, exact pixel rounding is fine.
还原现有比例,不要手动逆向推导(可使用dembrandt引擎)。 如果品牌已有网页字体,
get_typography
函数会返回从实时DOM计算出的真实字体大小、字重和行高——从这些数据中推断出底层比例,再用下面的方法规整,而非猜测原本的尺寸。详见
extract-design
base = 16px
、比例
1.25
为例:
Step计算公式精确值取整后用途
-216 ÷ 1.25²10.24px10px说明文字、超小标签
-116 ÷ 1.2512.80px13px标签、小字号文本
01616px16px正文(基础尺寸)
+116 × 1.2520px20px大字号正文、引导文本
+216 × 1.25²25px25pxH4标题
+316 × 1.25³31.25px31pxH3标题
+416 × 1.25⁴39.06px39pxH2标题
+516 × 1.25⁵48.83px49pxH1标题
+616 × 1.25⁶61.04px61px展示级标题
取整为整数像素或rem单位即可——比例体现的是设计意图,精确像素取整是可行的。

Design Tokens (CSS custom properties)

Design Tokens(CSS自定义属性)

css
:root {
  --text-xs:   0.625rem;  /* 10px  — caption */
  --text-sm:   0.813rem;  /* 13px  — label   */
  --text-base: 1rem;      /* 16px  — body    */
  --text-lg:   1.25rem;   /* 20px  — lead    */
  --text-xl:   1.563rem;  /* 25px  — h4      */
  --text-2xl:  1.938rem;  /* 31px  — h3      */
  --text-3xl:  2.438rem;  /* 39px  — h2      */
  --text-4xl:  3.063rem;  /* 49px  — h1      */
  --text-5xl:  3.813rem;  /* 61px  — display */
}
css
:root {
  --text-xs:   0.625rem;  /* 10px  — caption */
  --text-sm:   0.813rem;  /* 13px  — label   */
  --text-base: 1rem;      /* 16px  — body    */
  --text-lg:   1.25rem;   /* 20px  — lead    */
  --text-xl:   1.563rem;  /* 25px  — h4      */
  --text-2xl:  1.938rem;  /* 31px  — h3      */
  --text-3xl:  2.438rem;  /* 39px  — h2      */
  --text-4xl:  3.063rem;  /* 49px  — h1      */
  --text-5xl:  3.813rem;  /* 61px  — display */
}

Tailwind Config

Tailwind 配置

js
// tailwind.config.js
fontSize: {
  'xs':   ['0.625rem', { lineHeight: '1rem' }],
  'sm':   ['0.813rem', { lineHeight: '1.25rem' }],
  'base': ['1rem',     { lineHeight: '1.5rem' }],
  'lg':   ['1.25rem',  { lineHeight: '1.75rem' }],
  'xl':   ['1.563rem', { lineHeight: '2rem' }],
  '2xl':  ['1.938rem', { lineHeight: '2.25rem' }],
  '3xl':  ['2.438rem', { lineHeight: '2.5rem' }],
  '4xl':  ['3.063rem', { lineHeight: '1.1' }],
  '5xl':  ['3.813rem', { lineHeight: '1' }],
}
js
// tailwind.config.js
fontSize: {
  'xs':   ['0.625rem', { lineHeight: '1rem' }],
  'sm':   ['0.813rem', { lineHeight: '1.25rem' }],
  'base': ['1rem',     { lineHeight: '1.5rem' }],
  'lg':   ['1.25rem',  { lineHeight: '1.75rem' }],
  'xl':   ['1.563rem', { lineHeight: '2rem' }],
  '2xl':  ['1.938rem', { lineHeight: '2.25rem' }],
  '3xl':  ['2.438rem', { lineHeight: '2.5rem' }],
  '4xl':  ['3.063rem', { lineHeight: '1.1' }],
  '5xl':  ['3.813rem', { lineHeight: '1' }],
}

Why This Makes Typography Feel Cohesive

为何这样能让排版更连贯

Without a scale, designers and developers pick sizes by eye or habit (
14px
,
16px
,
18px
,
24px
,
32px
,
48px
). These feel subtly wrong because the intervals are uneven — the jump from 14→16 is small, 32→48 is large, and there is no underlying logic tying them together. The eye senses the inconsistency even when the viewer cannot name it.
With a modular scale, every size step carries the same visual weight of change. Hierarchy reads clearly because each level is a proportional step away from the next, not an arbitrary gap.
如果没有比例规范,设计师和开发人员会凭视觉或习惯选择字号(如
14px
16px
18px
24px
32px
48px
)。这些选择会显得微妙地不协调,因为字号间隔不均——14px到16px的跨度很小,32px到48px的跨度却很大,而且没有底层逻辑将它们关联起来。即使观者无法明确说出问题所在,视觉上也能感知到这种不一致。
使用Modular Scale后,每个字号层级的视觉变化权重一致。层级结构清晰可读,因为每个级别与下一级别都是成比例的差距,而非随意的间隔。

Minimum Font Size

最小字号规范

Body text base: 16px minimum. This is the browser default for good reason — it is the threshold below which reading comfort drops significantly, especially on screens.
  • 16px — standard body text, the default base
  • 14px — acceptable for secondary UI text (labels, captions, metadata) used sparingly
  • Below 14px — do not use. Even at high DPI, sub-14px text fails WCAG contrast requirements for normal text and creates accessibility issues.
In the modular scale, this means the base (
step 0
) should be 16px, and negative steps (step -1, step -2) should be used only for genuinely secondary content — never for body copy or primary labels.
The 1% heuristic. Sub-16px text is the rare exception (target: under ~1% of a page, never below 14px). Nobody counts characters, so apply it as a role test:
  • May go below 16px — a fixed whitelist of glanced-at roles: timestamps, captions, table metadata, helper text, fine print, badge labels.
  • Never — body copy, primary labels, list item titles, anything actually read to do the task.
Check: scan one screen, count distinct sub-16px roles. Two or three from the whitelist is healthy; five or more — or any reading content — means you've over-shrunk. That's layout density, not a type problem: cut what's shown rather than shrink the type to fit.
正文字号基础值:最小16px。 这是浏览器默认值是有原因的——低于这个阈值,阅读舒适度会显著下降,尤其是在屏幕上。
  • 16px ——标准正文字号,默认基础值
  • 14px ——可用于次要UI文本(标签、说明文字、元数据),但需谨慎使用
  • 低于14px ——禁止使用。即使在高DPI屏幕上,小于14px的文本也无法满足WCAG普通文本的对比度要求,会造成无障碍访问问题。
在Modular Scale中,这意味着基础值(0级)应为16px,负层级(-1级、-2级)仅应用于真正的次要内容——绝不能用于正文或主要标签。
1%原则。 小于16px的文本是罕见的例外(目标:占页面内容的1%以下,且绝不低于14px)。无需精确统计字符数,可按文本角色判断:
  • 可使用小于16px的场景——固定的快速浏览类角色:时间戳、说明文字、表格元数据、辅助文本、小字提示、徽章标签。
  • 禁止使用场景——正文、主要标签、列表项标题、任何用户需要阅读以完成任务的内容。
检查方法:浏览一屏内容,统计不同的小于16px文本角色。如果只有2-3种属于上述白名单角色,且无阅读类内容,即为合理;如果有5种以上,或包含阅读类内容,则说明过度缩小字号。这是布局密度问题,而非排版问题:应减少显示内容,而非缩小字号来适配。

Type Rendering Details

字体渲染细节

Size and ratio set the structure; these details determine whether the type actually reads well on screen.
字号和比例奠定了结构基础,而以下细节决定了字体在屏幕上的实际可读性。

Letter Spacing

字间距

  • Body and default text: keep tracking at
    0
    . Adding it to running text slows reading and makes the type feel loose.
  • Uppercase and small labels: the one place tracking helps, since capitals are visually tight. Cap it at
    0.04em
    , and reach for that only when the label genuinely needs air.
  • Pattern: zero on lowercase body, at most a hair (
    ≤ 0.04em
    ) on uppercase labels
    — never a blanket value. Over-tracking reads as dated, not premium.
  • 正文及默认文本: 字间距保持为
    0
    。给连续文本添加字间距会减慢阅读速度,使字体显得松散。
  • 大写文本和小标签: 这是字间距有用的场景,因为大写字母视觉上较为紧凑。最大不超过
    0.04em
    ,且仅在标签确实需要呼吸空间时使用。
  • 原则:小写正文字间距为0,大写标签最多添加细微间距(≤0.04em)——绝不能设置全局字间距。过度增加字间距会显得过时,而非高端。

Weight on Dark Backgrounds

深色背景下的字重

Light text on dark appears optically thinner — a halation effect where bright type bleeds into the dark field. Step up one weight to compensate: where regular (400) works on light, use medium or semibold for the equivalent text on dark. This keeps perceived weight consistent across modes instead of dark-mode text looking frail.
浅色文本在深色背景上视觉上会显得更细——这是光晕效应,明亮的文本会渗入深色背景。需提高一个字重进行补偿:在浅色背景上使用常规字重(400)的文本,在深色背景上应使用中等或半粗体。这样能保证在不同模式下,文本的感知字重一致,避免深色模式下文本显得单薄。

Monospace

等宽字体

Monospace is for technical content where character alignment matters — code, IDs, numeric tables, diffs. Don't use it as a default UI typeface, and avoid monospace + uppercase (even widths plus tall capitals are hard to scan).
等宽字体适用于字符对齐至关重要的技术内容——代码、ID、数值表格、差异对比。不要将其作为默认UI字体,避免等宽字体+大写文本组合(等宽字符加高大写字母难以快速阅读)。

Type Scale by Page Context

按页面场景选择字体比例

Landing pages and marketing surfaces benefit from large, expressive type — steps +4 to +6 for headlines create drama and brand presence.
Feature pages and application UI should use a more controlled range — steps +2 to +3 for headings, with body text at step 0. Oversized headings inside a functional UI distract from the content and make the layout feel unbalanced.
Match the ratio and scale usage to the purpose of the surface, not just the brand.
着陆页和营销页面适合使用大尺寸、富有表现力的字体——+4到+6级标题能营造戏剧效果和品牌存在感。
功能页和应用UI应使用更克制的比例范围——标题使用+2到+3级,正文使用0级。功能UI内的超大标题会分散用户对内容的注意力,使布局显得失衡。
根据页面用途而非仅品牌风格选择比例和字体范围。

Heading Hierarchy and Page Complexity

标题层级与页面复杂度

A successful heading scale uses more than just font size to distinguish levels. It also respects the cognitive limits of the page.
成功的标题比例不仅依靠字号区分层级,还需尊重页面的认知极限。

Tools for Differentiation

层级区分工具

If headings only differ by small increments of size, they become hard to distinguish at a glance. Use these tools to create a more meaningful scale:
  • Capitalization: Use uppercase (
    text-transform: uppercase
    ) for small, lower-level headings (H4–H5) to give them visual weight without needing large sizes.
  • Letter Spacing: When using uppercase or bold headings, add at most a hair of
    letter-spacing
    (
    ≤ 0.04em
    ) — and only when the heading genuinely needs the air. Keep it subtle; over-tracking reads as dated, not premium.
  • Color: Use your brand primary colour or a slightly muted grey for secondary headings to differentiate them from the main black/dark-grey text.
  • Style: Use italics or subtle underlines for supplementary or metadata-style headings.
如果标题仅通过细微的字号增量区分,用户一眼难以分辨。可使用以下工具创建更清晰的层级:
  • 大小写: 对小型、低层级标题(H4–H5)使用大写(
    text-transform: uppercase
    ),无需增大字号即可赋予其视觉权重。
  • 字间距: 使用大写或粗体标题时,最多添加细微的
    letter-spacing
    (≤0.04em)——且仅在标题确实需要呼吸空间时使用。保持微妙;过度增加字间距会显得过时。
  • 颜色: 使用品牌主色或稍暗的灰色作为次要标题颜色,与主黑色/深灰色文本区分开。
  • 样式: 对补充性或元数据风格的标题使用斜体或细微下划线。

The Rule of Three (H1–H3)

三级原则(H1–H3)

Most well-designed pages require only three levels of heading hierarchy (H1, H2, H3).
  • Simplicity: H1–H3 is enough to cover the page title, section titles, and sub-sections.
  • H4–H6 is a complexity smell, not a typography problem. If you find yourself reaching for H4, H5, or H6, the page is trying to do too much. Adding smaller heading levels only hides the symptom. Read it as a signal and make a structural decision instead:
    • Split — the page is really two features, or an in-page sub-page. Break it across pages or a modular structure (sidebar, tabs, master-detail).
    • Remove — the deep section may not earn its place at all.
    • Simplify — flatten the sub-hierarchy so it fits within H1–H3.
    • Hide behind an opening/closing element — push secondary content into a modal, accordion, or panel (see
      information-architecture
      ).
A page that needs 6 levels of headings is a page that most users will stop reading.
大多数设计良好的页面仅需要三级标题层级(H1、H2、H3)
  • 简洁性: H1–H3足以覆盖页面标题、章节标题和子章节。
  • H4–H6是复杂度信号,而非排版问题。 如果需要使用H4、H5或H6,说明页面承载的内容过多。添加更小的标题层级只是掩盖症状。应将其视为信号,做出结构上的决策
    • 拆分页面——该页面实际上是两个功能,或是页面内的子页面。可将内容拆分到多个页面,或使用模块化结构(侧边栏、标签页、主详情布局)。
    • 移除内容——深层章节可能根本没有存在的必要。
    • 简化层级——将子层级扁平化,使其适配H1–H3范围。
    • 隐藏在可展开/收起元素中——将次要内容放入模态框、折叠面板或侧边栏(详见
      information-architecture
      )。
需要6级标题的页面,大多数用户会停止阅读。

Reading Comfort and Editorial Patterns

阅读舒适度与编辑模式

Typography is not just about size — it is about the rhythm and structure of the content.
排版不仅关乎字号——还关乎内容的节奏和结构。

Line Length (Measure)

行宽(Measure)

For optimal reading comfort, keep body text between 45–75 characters per line (approx. 500–700px).
  • Lines that are too long make it hard for the eye to find the start of the next line.
  • Lines that are too short break the reading rhythm and create distracting "rags."
为获得最佳阅读舒适度,正文每行应保持在45–75个字符(约500–700px)。
  • 行宽过长会导致眼睛难以找到下一行的开头。
  • 行宽过短会打断阅读节奏,造成杂乱的“参差不齐”效果。

Measure, Leading and Size Move Together

行宽、行高与字号协同调整

Line length, line-height (leading) and font size are not three independent knobs — they are one system. This is a foundational typographic principle (Bringhurst's The Elements of Typographic Style) repeatedly validated on digital platforms, and it underpins the line-height ramps in the Material and Apple HIG type scales.
The longer the measure, the more leading the eye needs to track from the end of one line back to the start of the next. A tight line-height that reads fine on a narrow column becomes tiring on a wide one.
MeasureRecommended body line-height
Narrow (~45ch)1.4
Comfortable (55–66ch)1.5
Wide (~75ch)1.6–1.7
Practical rules:
  • Body text: line-height 1.4–1.7, never below 1.4 for multi-line copy. WCAG SC 1.4.12 also requires text to stay readable when users override line-height to at least 1.5, so design with that headroom.
  • Headings: large type needs less leading — tighten to 1.1–1.25 as size grows, or the lines drift apart and stop reading as one unit. Leading and size are inversely related.
  • Fix the cause, not the symptom: if a line of body text feels hard to read, widen the leading or narrow the measure — don't just shrink the font. The three move together.
行宽、行高(leading)和字号并非三个独立的调节项——它们是一个系统。这是排版的基本原则(Bringhurst的《排版风格要素》),并在Material和Apple HIG字体比例的行高梯度中反复得到验证。
行宽越长,眼睛需要更多行高来从一行末尾追踪到下一行开头。在窄列中阅读舒适的紧凑行高,在宽列中会让人感到疲劳。
行宽推荐正文行高
窄(约45ch)1.4
舒适(55–66ch)1.5
宽(约75ch)1.6–1.7
实用规则:
  • 正文: 行高为1.4–1.7,多行文本的行高绝不能低于1.4。WCAG SC 1.4.12还要求用户将行高覆盖为至少1.5时文本仍可读,因此设计时需预留空间。
  • 标题: 大字号需要更小的行高——随着字号增大,行高收紧至1.1–1.25,否则行间距过大会导致文本无法作为一个整体阅读。行高与字号成反比。
  • 解决根源,而非症状: 如果正文行难以阅读,应增大行高缩小行宽——不要仅缩小字号。这三者需协同调整。

Line Clamping

文本截断

In grids, cards, or lists with unpredictable content lengths, clamp text to keep a consistent visual rhythm and equal-height cards. Limit descriptions to 2–3 lines so all cards in a row stay the same height.
Multi-line clamp. Pair the standard
line-clamp
with the
-webkit-
fallback — the legacy
-webkit-box
form is still required for full browser support, so keep both.
css
.card-description {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
Single-line clamp. For titles and labels that must never wrap, use the ellipsis pattern instead.
css
.card-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
Inside flex or grid. Truncation silently fails when the item can't shrink below its content width. Add
min-width: 0
(or
min-inline-size: 0
) to the clamped child so it is allowed to narrow.
Accessibility — never lose the content. Clamping hides text visually only; the full string stays in the DOM and is read in full by screen readers, but a sighted user can no longer see it. Always give them a path to the rest:
  • Provide a
    title
    attribute (or accessible tooltip) carrying the full text, or
  • Link to a detail view / "Read more" where the complete content lives.
Never clamp text that the user must read to act (prices, errors, legal copy, primary instructions) — clamp only supporting descriptions where truncation is safe.
在网格、卡片或内容长度不可预测的列表中,截断文本以保持一致的视觉节奏和等高卡片。描述文本限制为2–3行,使同一行的所有卡片高度一致。
多行截断。 将标准
line-clamp
-webkit-
兼容写法结合使用——旧版
-webkit-box
写法仍需用于全浏览器支持,因此需同时保留两种写法。
css
.card-description {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
单行截断。 对于绝不能换行的标题和标签,使用省略号模式。
css
.card-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
Flex或Grid布局内的截断。 当元素无法缩小到内容宽度以下时,截断会静默失效。给截断的子元素添加
min-width: 0
(或
min-inline-size: 0
),使其允许缩小。
无障碍访问——绝不丢失内容。 截断仅隐藏文本的视觉显示;完整文本仍保留在DOM中,屏幕阅读器会完整读取,但视力正常的用户无法看到。必须为用户提供查看完整内容的途径:
  • 添加包含完整文本的
    title
    属性(或无障碍提示框),或
  • 链接到详情页/“阅读更多”页面,展示完整内容。
绝不要截断用户必须阅读才能操作的文本(价格、错误提示、法律文本、主要说明)——仅截断支持性描述文本,确保截断是安全的。

Editorial Hierarchy

编辑层级

Use specific typographic roles to provide context and guide the user through the story:
RoleVisual TreatmentPurpose
Pre-title (Eyebrow)Small (12–13px), often all-caps, subtle letter-spacing (
≤ 0.04em
), muted colour
Provides context or category without distracting from the main heading
HeadingLarge, bold, modular scale step +3 to +5The primary hook or subject
Ingress (Lead text)Larger than body (step +1), slightly bolder or higher line-heightSummarises the core value; bridging the heading and the body copy
BodyBase size (16px), regular weight, comfortable line-height (1.5)The primary reading experience
使用特定的排版角色提供上下文,引导用户理解内容:
角色视觉处理用途
前置标题(Eyebrow)小字号(12–13px),通常为全大写,细微字间距(≤0.04em),柔和颜色提供上下文或分类,不分散主标题的注意力
主标题大字号,粗体,Modular Scale +3到+5级核心钩子或主题
引导文本(Lead text)比正文大(+1级),稍粗或行高更大总结核心价值,衔接主标题和正文
正文基础字号(16px),常规字重,舒适行高(1.5)主要阅读内容

Wording and Voice

措辞与语气

  • Use active voice. "Get started" instead of "Getting started is easy."
  • Be punchy. Use clear, descriptive labels that promise a result.
  • Consistency. Use the same terms for the same actions throughout the product.
  • 使用主动语态。 比如用“立即开始”代替“开始使用很简单”。
  • 简洁有力。 使用清晰、描述性的标签,承诺明确的结果。
  • 保持一致。 整个产品中对相同操作使用相同术语。

Responsive Type Scale

响应式字体比例

The scale compresses on smaller viewports by tightening the ratio, not by manually overriding individual sizes. The floor (body, labels) stays stable — readability has a hard minimum. The ceiling (H1, display) shrinks significantly. Every heading level scales proportionally because the ratio changes; hierarchy stays internally coherent.
Rule: use a wider ratio on desktop (more drama), a tighter ratio on mobile (more restraint). The base stays the same. The top end gives way.
  • Desktop → wider ratio (e.g. 1.25–1.333): large contrast between H1 and body
  • Tablet → moderate ratio (e.g. 1.200): scale pulls in
  • Mobile → tight ratio (e.g. 1.125): H1 is notably smaller, body is unchanged
Never shrink the scale from the bottom. Body text at 16px is already a floor — compression always comes from the top.
在小视口上,字体比例通过收紧比例值来压缩,而非手动覆盖单个字号。底层(正文、标签)保持稳定——可读性有硬性最小值。顶层(H1、展示级标题)大幅缩小。每个标题层级按比例缩放,因为比例值发生变化;层级内部保持连贯。
规则: 桌面端使用更宽的比例(更具戏剧性),移动端使用更紧凑的比例(更克制)。基础值保持不变,顶层标题缩小。
  • 桌面端 → 宽比例(如1.25–1.333):H1与正文的对比度大
  • 平板端 → 中等比例(如1.200):比例收紧
  • 移动端 → 紧凑比例(如1.125):H1明显更小,正文不变
绝不要从底层缩小比例。16px的正文字号已是下限——压缩始终从顶层开始。

Fluid Type with
clamp()

使用
clamp()
实现流体字体

Instead of stepping sizes at fixed breakpoints, let the top end scale smoothly between a floor and a ceiling using CSS
clamp(MIN, PREFERRED, MAX)
. The viewport-relative middle term does the scaling; the floor and ceiling stop it from ever getting too small or too large.
css
:root {
  --text-body: 1rem;                         /* the floor stays fixed */
  --text-h1: clamp(2rem, 1.5rem + 3vw, 3.5rem);
}
  • The
    MIN
    is the mobile size, the
    MAX
    is the desktop size — the same floor/ceiling thinking as the stepped scale, just interpolated.
  • Apply
    clamp()
    to the top of the scale (headings, display). Keep body and labels at a fixed size — readability has a hard minimum, so the floor must not move.
  • Include a
    rem
    term in the preferred value (e.g.
    1.5rem + 3vw
    , not
    3vw
    alone) so the text still responds to user zoom and root font-size — a pure
    vw
    value breaks zoom accessibility.
无需在固定断点处切换字号,使用CSS
clamp(MIN, PREFERRED, MAX)
让顶层标题在最小值和最大值之间平滑缩放。视口相关的中间值实现缩放;最小值和最大值防止文本过小或过大。
css
:root {
  --text-body: 1rem;                         /* 底层保持固定 */
  --text-h1: clamp(2rem, 1.5rem + 3vw, 3.5rem);
}
  • MIN
    是移动端字号,
    MAX
    是桌面端字号——与阶梯式比例的下限/上限思路相同,只是实现了插值过渡。
  • clamp()
    应用于比例顶层(标题、展示级文本)。保持正文和标签为固定字号——可读性有硬性最小值,因此底层不能变动。
  • 在首选值中包含
    rem
    项(如
    1.5rem + 3vw
    ,而非仅
    3vw
    ),这样文本仍能响应用户缩放和根字号设置——纯
    vw
    值会破坏缩放无障碍性。

Review Checklist

审核检查清单

  • Are all font sizes derived from a single base + ratio?
  • Is the base size 16px or larger?
  • Is 14px used only for secondary/metadata text, never for body copy?
  • Is nothing below 14px used anywhere in the UI?
  • Counting distinct sub-16px text roles on a screen, are there only a few (≤3) and all from the secondary whitelist — never reading content?
  • Is body letter-spacing 0, with uppercase-label tracking capped at
    0.04em
    and used only when air is needed?
  • Does light-on-dark text use a slightly heavier cut to compensate for halation?
  • Is monospace scoped to technical content, never used as a default or with uppercase?
  • Is there at least 3–4 distinct steps between body text and the largest heading?
  • Are adjacent steps (e.g. body vs. label) different enough to be distinguishable at a glance?
  • Are font size tokens named by role (
    --text-body
    ,
    --text-h1
    ) or step (
    --text-base
    ,
    --text-2xl
    ), not by raw pixel value?
  • Does the chosen ratio suit the UI density? (tight ratio for data-heavy UIs, wider ratio for marketing)
  • Is body text line length between 45–75 characters?
  • Does body line-height scale with the measure (≈1.4 narrow → ≈1.6+ wide), staying ≥1.4 and leaving 1.5 override headroom for WCAG 1.4.12?
  • Is heading leading tightened (≈1.1–1.25) as size grows, so large type still reads as one unit?
  • Is line-clamping used to keep grid/card layouts consistent?
  • Does clamped text keep a path to the full content (
    title
    /tooltip or detail view), and is must-read content never clamped?
  • If fluid type (
    clamp()
    ) is used, is it applied only to the top of the scale, with a
    rem
    -based preferred term so zoom still works?
  • Are editorial roles like pre-titles and lead text used to improve scannability?
  • Are headings differentiated by more than just size (e.g., color, case, spacing)?
  • Is the heading hierarchy limited to H1–H3 per view where possible?
  • 所有字号是否都源自单一基础值+比例值?
  • 基础字号是否为16px或更大?
  • 14px是否仅用于次要/元数据文本,从未用于正文?
  • UI中是否没有使用小于14px的文本?
  • 统计一屏内不同的小于16px文本角色,是否仅有少数(≤3种)且均属于次要白名单——无阅读类内容?
  • 正文字间距是否为0,大写标签的字间距是否最多为
    0.04em
    且仅在需要时使用?
  • 浅色文本在深色背景上是否使用稍重的字重以补偿光晕效应?
  • 等宽字体是否仅用于技术内容,从未作为默认字体或与大写文本组合使用?
  • 正文与最大标题之间是否至少有3–4个不同的层级?
  • 相邻层级(如正文与标签)的差异是否足够大,一眼可辨?
  • 字号令牌是否按角色(
    --text-body
    ,
    --text-h1
    )或层级(
    --text-base
    ,
    --text-2xl
    )命名,而非原始像素值?
  • 选择的比例值是否适配UI密度?(紧凑比例用于数据密集型UI,宽比例用于营销场景)
  • 正文字符行宽是否在45–75之间?
  • 正文行高是否随行宽缩放(窄列≈1.4 → 宽列≈1.6+),且保持≥1.4,为WCAG 1.4.12预留1.5的覆盖空间?
  • 标题行高是否随字号增大而收紧(≈1.1–1.25),使大字号仍能作为整体阅读?
  • 是否使用文本截断保持网格/卡片布局一致?
  • 截断文本是否提供查看完整内容的途径(
    title
    /提示框或详情页),且绝未截断必须阅读的内容?
  • 如果使用流体字体(
    clamp()
    ),是否仅应用于比例顶层,且首选值包含
    rem
    项以保证缩放正常工作?
  • 是否使用前置标题、引导文本等编辑角色提高可读性?
  • 标题是否通过字号以外的方式区分(如颜色、大小写、间距)?
  • 每个视图的标题层级是否尽可能限制在H1–H3?

Common Anti-Patterns

常见反模式

Anti-patternProblemFix
Sizes like 14, 15, 16, 17px used side by sideSteps too small to read as distinct levelsUse at minimum a 1.125 ratio so each step is perceptible
Arbitrary sizes with no relationship (13, 18, 27, 36px)No underlying logic — hierarchy feels accidentalRegenerate from a single base and ratio
Pixel values hard-coded in components instead of tokensScale changes require hunting through every fileDefine once as CSS custom properties or design tokens
Same scale used for display headings and dense data tablesOne ratio rarely serves both extremes wellUse a tighter ratio (1.125) for data, wider (1.25–1.333) for marketing contexts
Letter-spacing added to running body textLoosens the type and slows readingKeep body tracking at 0; add at most
0.04em
to uppercase labels when air is needed
Regular-weight white text on a dark backgroundHalation makes it look thin and frailStep up one weight (medium/semibold) for light-on-dark text
Monospace as a default UI font, or monospace + uppercaseHard to scan, reads as "unstyled"Scope monospace to code/IDs/numeric data only
反模式问题修复方案
同时使用14、15、16、17px等字号层级差异过小,无法区分至少使用1.125的比例值,使每个层级的差异可感知
使用无关联的随意字号(13、18、27、36px)无底层逻辑——层级显得随意从单一基础值和比例值重新生成字号
组件中硬编码像素值而非使用令牌比例变更时需逐个文件修改在CSS自定义属性或设计令牌中统一定义一次
展示标题和密集数据表使用相同比例单一比例难以同时适配两个极端场景数据密集型场景使用紧凑比例(1.125),营销场景使用宽比例(1.25–1.333)
连续正文添加字间距字体松散,减慢阅读速度正文字间距保持为0;仅在需要时给大写标签添加最多
0.04em
的字间距
深色背景上使用常规字重的浅色文本光晕效应导致文本显得单薄浅色文本在深色背景上提高一个字重(中等/半粗体)
等宽字体作为默认UI字体,或等宽字体+大写文本难以阅读,显得“未样式化”等宽字体仅用于代码/ID/数值数据