大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
文字排版
这一课你将能做到
- 用 font-family 写出跨平台字体栈
- 控制字号、粗细、行高、对齐、装饰线、字间距
- 用 @font-face 加载自定义字体
- 写出符合可读性标准的正文排版
为什么要学
网页 90% 是文字,文字排版直接决定用户能不能读下去。line-height 太挤,用户读两行就走;字体栈写错,Mac 用户看到的是漂亮苹方,Windows 用户看到的是默认衬线,体验天差地别。
人话:排版就是文字的「呼吸感」——行距像楼层高度,字距像人和人的距离,太挤会窒息,太松会疏离。
先建立图像
<style>
body {
font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
font-size: 16px;
line-height: 1.6;
color: #333;
}
h1 { font-size: 2rem; font-weight: 700; letter-spacing: 0.05em; }
.intro { text-align: justify; text-indent: 2em; }
.link { text-decoration: none; color: #0366d6; }
.link:hover { text-decoration: underline; }
</style>
<h1>字排版示例</h1>
<p class="intro">这段文字两端对齐、首行缩进 2em。一段好的排版应该让读者忘记排版本身,专注于内容。</p>
<a href="#" class="link">这是一个无下划线的链接,悬停才出现</a>
跟着做
步骤 1:font-family 字体栈
body {
font-family:
-apple-system, /* iOS/macOS 系统字体 */
"PingFang SC", /* 苹果中文苹方 */
"Microsoft YaHei", /* 微软雅黑 */
"Helvetica Neue", /* 经典西文 */
Arial, /* 兜底西文 */
sans-serif; /* 最终兜底:任何无衬线 */
}
浏览器从左往右找,找到第一个能用的就用。最后一定要写 sans-serif 或 serif 兜底。
带空格或中文的字体名要加引号。
步骤 2:font-size 与 font-weight
h1 { font-size: 2rem; }
p { font-size: 1rem; }
.small { font-size: 0.875rem; }
.thin { font-weight: 300; }
.normal { font-weight: 400; } /* 等价于 normal */
.bold { font-weight: 700; } /* 等价于 bold */
font-weight 取值 100-900,步进 100。但能否真的显示对应粗细,要看字体本身是否提供了这些字重。
步骤 3:line-height 行高
p { line-height: 1.6; } /* 推荐:无单位数字,相对字号 */
p { line-height: 1.6em; } /* 也行但会继承计算后的值 */
p { line-height: 24px; } /* 死板不推荐 */
正文推荐 1.5-1.7,标题 1.2-1.4。
强烈建议用无单位数字:子元素继承的是「倍数」而不是「算出来的像素」,更灵活。
步骤 4:text-align 与 text-indent
.left { text-align: left; } /* 默认 */
.center { text-align: center; }
.right { text-align: right; }
.justify { text-align: justify; } /* 两端对齐 */
p { text-indent: 2em; } /* 首行缩进两字符 */
中文书籍习惯首行缩进 2em,西文习惯段间距而不缩进。
步骤 5:text-decoration 装饰线
a { text-decoration: none; } /* 去掉链接下划线 */
.u { text-decoration: underline; }
.t { text-decoration: line-through; } /* 删除线 */
.fancy {
text-decoration: underline wavy red; /* 红色波浪下划线 */
text-underline-offset: 4px; /* 下划线偏移 */
}
步骤 6:letter-spacing 与 word-spacing
h1 { letter-spacing: 0.05em; } /* 字间距,标题常用 */
.upper { letter-spacing: 0.2em; text-transform: uppercase; }
p { word-spacing: 0.1em; } /* 词间距(对中文效果有限) */
步骤 7:@font-face 加载自定义字体
@font-face {
font-family: "MyBrand";
src: url("fonts/mybrand.woff2") format("woff2"),
url("fonts/mybrand.woff") format("woff");
font-weight: 400;
font-style: normal;
font-display: swap; /* 字体加载时先用兜底字体,加载完替换 */
}
body { font-family: "MyBrand", sans-serif; }
font-display: swap 防止「字体加载期间页面空白」(FOIT)。
步骤 8:实战——博客正文排版
<style>
.article {
max-width: 65ch; /* 每行最多 65 字符 */
margin: 0 auto;
font-family: Georgia, "Songti SC", serif;
font-size: 18px;
line-height: 1.75;
color: #2c3e50;
}
.article h2 {
font-size: 1.5rem;
margin: 2em 0 1em;
letter-spacing: 0.02em;
}
.article p { margin: 1em 0; text-align: justify; }
</style>
<div class="article">
<h2>一、排版即阅读体验</h2>
<p>好的排版像空气——你察觉不到它的存在,但一旦缺失就会窒息。</p>
</div>
讲清楚要点
- 字体栈的意义:操作系统字体不同,必须给兜底。中文站至少要 PingFang + 雅黑 + sans-serif。
- line-height 用无单位:继承倍数而不是固定值,子元素自适应。
- font-weight 数字 vs 关键字:
bold = 700、normal = 400;300 以下多数中文字体不支持。 text-align: justify中文慎用:会导致字间距忽大忽小。西文效果好。- @font-face 用 woff2:压缩率最高;woff 兜底;ttf/eot/svg 已过时。
你可能会懵的地方
-
为什么中文不要 letter-spacing? 中文方块字本身就紧凑,加字距会显得散。西文大写标题加 letter-spacing 效果才好。
-
衬线和无衬线怎么选? 屏幕正文用无衬线(清晰),长篇打印用衬线(优雅)。中文场景正文一律无衬线。
-
font-display各值区别?auto浏览器决定、block短暂不可见后替换、swap立即用兜底字体后替换、fallback短暂 block 再 swap、optional慢网就用兜底。 -
text-indent: -9999px是干嘛的? 老的图片替换文字技巧,把文字推出屏幕。现在用aria-label更友好。 -
em在 text-indent 里相对谁? 相对当前元素的字号。text-indent: 2em永远是「两个汉字宽度」。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
font-family: 微软雅黑 | 中文未加引号 | "Microsoft YaHei" 或 "微软雅黑" |
line-height: 1.6px | 行高太小文字重叠 | line-height: 1.6 无单位 |
全局 * { line-height: 1.6em } | 子元素继承计算后的 px 值 | 用无单位 1.6 |
font-weight: 350 | 大多数字体没这个字重 | 用 100 整数倍 |
@font-face 用 ttf 不压缩 | 文件几 MB 拖慢首屏 | 转 woff2 + font-display: swap |
中文正文用 text-align: justify | 字距忽大忽小 | 中文用默认左对齐 |
卡点急救
- 自定义字体不生效:F12 → Network 看字体文件是否 404;检查
format()是否匹配实际文件格式。 - 字体闪烁(FOUT):
font-display: swap导致;可改用fallback或预加载<link rel="preload" as="font">。 - Mac 和 Windows 显示不同:字体栈没写全,确认两端的兜底字体都覆盖了。
面试常问
-
line-height 的继承机制? 无单位值继承「倍数」,子元素按自己的字号重新计算;带单位值(px/em)继承「计算后的具体值」,子元素无法自适应。
-
怎么优化 Web 字体加载? woff2 格式 + 子集化(只保留用到的字符)+ preload + font-display: swap + CDN。
-
font-family 什么时候要加引号? 字体名包含空格、中文、特殊字符时。
Arial不用,"Helvetica Neue"必须。
自测三问
line-height: 1.5和line-height: 1.5em在继承上有何区别?font-display: swap解决了什么问题?- 为什么字体栈要以
sans-serif结尾?
小结一句话
排版的关键是「克制」:合适的字体栈、1.5-1.7 的行高、16-18px 的正文、65 字符的行宽,把这四件事做好,超过 90% 的网站。
延伸
- MDN 文本样式基础
- 下一课:盒模型,CSS 布局的根基。