WinddSnow

CSS-Fonts-and-Text-Styling

字数统计: 5.1k阅读时长: 20 min
2026/07/28

第21课:字体与文本样式

文字是网页内容的核心载体。CSS 提供了两套属性体系来控制文字的呈现:字体属性(Font Properties)决定文字使用哪种字体、多大、是否加粗倾斜——即“字符长什么样”;文本样式属性(Text Properties)控制文字的排列方式、行高、缩进、装饰线——即“文字怎么排”。理解这两者的分工以及关键属性的工作原理,是实现优雅排版的基础。本节课将系统讲解 font-family 与后备字体栈、@font-face 自定义字体、line-height 的行盒机制,以及 white-space 和文本溢出处理。


1. 字体属性:控制字符的形态

1.1 font-family:字体族系与后备字体栈

font-family 指定文字的字体。它接受一个按优先级排序的字体列表,浏览器从左到右尝试,使用第一个在当前系统中可用的字体。

1
2
3
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
}

后备字体栈的设计原则

  1. 最左侧是首选字体(通常是具体品牌的字体,如 Roboto 或系统字体关键字)。
  2. 中间是平台备选字体(如 macOS 的 -apple-system、Windows 的 "Segoe UI")。
  3. 最右侧必须是通用字体族(Generic Family),作为最终兜底。

五个通用字体族

通用族名 说明 典型代表字体
serif 衬线字体:笔画末端有装饰线,适合长文阅读。 Times New Roman、Georgia、宋体
sans-serif 无衬线字体:笔画简洁无装饰,适合屏幕阅读。 Arial、Helvetica、微软雅黑、黑体
monospace 等宽字体:每个字符占据相同宽度,适合代码展示。 Courier New、Consolas、Fira Code
cursive 手写体/草书:模拟手写风格。 Comic Sans MS、Brush Script MT
fantasy 装饰性字体:用于标题或特殊效果。 Impact、Papyrus

包含空格的字体名必须用引号包裹:

1
2
3
h1 {
font-family: "Times New Roman", "宋体", serif;
}

系统字体关键字(现代最佳实践):
使用 system-ui 通用关键字可直接调用操作系统默认 UI 字体,无需维护长串的后备列表。

1
2
3
body {
font-family: system-ui, -apple-system, sans-serif;
}

system-ui 在各平台对应的默认字体:

  • Windows:Segoe UI
  • macOS / iOS:San Francisco(-apple-system)
  • Android:Roboto
  • Linux:取决于发行版(通常是 Noto Sans 或 DejaVu Sans)

1.2 font-size:字号与单位

font-size 定义字符的大小。

常用单位对比

单位 类型 说明 典型场景
px 绝对单位 像素。固定大小,不受父元素影响。 需要精确控制尺寸的场景。
em 相对单位 相对于父元素font-size1em = 父元素字号。 组件内部的相对缩放(如按钮内文字)。
rem 相对单位 相对于根元素<html>)的 font-size1rem = 根字号。 全局一致的相对字号,推荐用于主体文字。
% 相对单位 相对于父元素字号的百分比。 em 等价,150% = 1.5em
vw 视口单位 1vw = 视口宽度的 1%。 响应式标题、大屏装饰文字。

em 的复合效应(易错点)
em 是相对于**父元素计算后的 font-size**,在嵌套结构中会逐层放大或缩小,形成“复合”效果。

1
2
3
4
5
6
7
8
9
<div style="font-size: 16px;">
第一层 (16px)
<div style="font-size: 1.5em;">
第二层 (16 × 1.5 = 24px)
<div style="font-size: 1.5em;">
第三层 (24 × 1.5 = 36px) ← 逐层放大!
</div>
</div>
</div>

若希望各层级保持一致,应使用 rem

1
2
3
4
5
6
7
8
9
<div style="font-size: 16px;">
第一层 (16px)
<div style="font-size: 1.5rem;">
第二层 (假设根字号 16px,则 = 24px)
<div style="font-size: 1.5rem;">
第三层 (仍是 24px) ← 不受父层影响
</div>
</div>
</div>

推荐全局设置

1
2
3
4
5
6
html {
font-size: 16px; /* 或 62.5%(即 10px)以便用 rem 直接换算 */
}
body {
font-size: 1rem; /* 16px */
}

1.3 font-weight:字重(粗细)

font-weight 控制文字的粗细程度。

关键词 对应数值 说明
normal 400 常规粗细(默认)。
bold 700 加粗。
lighter 比父元素细 相对值。
bolder 比父元素粗 相对值。

也可以直接使用数值(100900,以 100 为增量):

  • 100:Thin(极细)
  • 300:Light(细)
  • 400:Regular(常规)
  • 500:Medium(中等)
  • 600:Semi Bold(半粗)
  • 700:Bold(粗)
  • 900:Black(极粗)

前提条件:数值字重仅在字体文件包含对应粗细的字体时才会生效。如果字体仅有 400700 两种粗细,则 font-weight: 500 会映射到 400 渲染。

1.4 font-style:斜体与伪斜体

说明
normal 正常字体(默认)。
italic 真斜体。使用字体文件中专门设计的斜体变体。
oblique 伪斜体。浏览器对正常字体进行机械倾斜模拟。

大多数情况下,italicoblique 的视觉效果相似。但当字体缺乏真斜体时,italic 也会退化为模拟倾斜。

1.5 font 简写属性

font 属性可以一次性设置多个字体相关属性,但必须遵循严格的顺序且**必填 font-sizefont-family**。

语法顺序

1
font: [font-style] [font-variant] [font-weight] font-size[/line-height] font-family
1
2
3
p {
font: italic small-caps bold 16px/1.5 "Helvetica Neue", sans-serif;
}

注意:未显式指定的子属性会被重置为初始值。若只写 font: 16px sans-serif;,则 font-stylefont-variantfont-weight 均被重置为 normal,可能意外覆盖之前的样式。


2. @font-face:加载自定义 Web 字体

@font-face 允许开发者加载服务器上的字体文件,使网页突破用户本地字体的限制,实现品牌定制的排版。

1
2
3
4
5
6
7
8
9
10
11
12
@font-face {
font-family: 'MyCustomFont';
src: url('/fonts/MyCustomFont.woff2') format('woff2'),
url('/fonts/MyCustomFont.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}

body {
font-family: 'MyCustomFont', sans-serif;
}

2.1 src 与字体格式

src 指定字体文件的 URL 和格式。推荐使用多格式、按优先级排列的策略。

格式 文件扩展名 说明 使用建议
woff2 .woff2 压缩效率最高,文件最小。所有现代浏览器均支持。 首选格式
woff .woff 上一代压缩格式,浏览器支持极广。 第二备选
truetype .ttf 未压缩,文件较大。 仅作为老浏览器后备。
opentype .otf 功能丰富,但文件较大。 需要高级排版特性时使用。
eot .eot 仅 IE 支持。 现代项目无需包含。

2.2 font-display:字体加载策略

font-display 控制自定义字体加载期间文字的渲染行为,直接影响用户体验(特别是首屏加载时)。

行为描述
auto 浏览器默认策略(通常等同于 block)。
block 短暂隐藏文字(约 3 秒),等待字体加载。若超时未加载,使用后备字体。不推荐——导致文字不可见。
swap 立即显示后备字体,字体加载完成后平滑切换。这是推荐值——用户始终能看到文字,无“闪烁消失”期。
fallback 短暂隐藏(约 100ms)。若此时间内未加载,使用后备字体。之后不再切换(即使字体加载完成)。适用于对字体要求不极端的场景。
optional fallback 类似,但完全依赖网络状况。若字体未能快速加载,则放弃加载并使用后备字体。适用于网络较差的移动端。

最佳实践:对正文内容使用 font-display: swap,确保文字始终可见;对图标字体或品牌 Logo 字体可考虑 blockfallback

2.3 多字重与多风格的加载

一个字体族通常包含多个变体文件(不同粗细、不同风格),每个变体需要一个独立的 @font-face 声明,并使用相同的 font-family 名称,通过 font-weightfont-style 区分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@font-face {
font-family: 'Inter';
src: url('/fonts/Inter-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}

@font-face {
font-family: 'Inter';
src: url('/fonts/Inter-Bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}

@font-face {
font-family: 'Inter';
src: url('/fonts/Inter-Italic.woff2') format('woff2');
font-weight: 400;
font-style: italic;
font-display: swap;
}

使用时,浏览器会自动匹配对应粗细和风格的字体文件:

1
2
3
4
5
6
7
8
9
10
11
12
body {
font-family: 'Inter', sans-serif;
font-weight: 400; /* 加载 Inter-Regular.woff2 */
}

strong {
font-weight: 700; /* 加载 Inter-Bold.woff2 */
}

em {
font-style: italic; /* 加载 Inter-Italic.woff2 */
}

3. 文本样式属性:控制排列与对齐

3.1 text-align:水平对齐

说明
left 左对齐(ltr 书写模式下的默认值)。
right 右对齐。
center 居中。
justify 两端对齐(拉伸单词/字符间距使每行等宽)。
start 对齐到书写模式的行首(逻辑属性,推荐)。
end 对齐到书写模式的行尾(逻辑属性,推荐)。
1
2
3
p {
text-align: justify; /* 两端对齐 */
}

注意text-align块级容器内的行内内容生效,不能直接用于行内元素自身来居中。

3.2 text-align-last:最后一行的对齐方式

当段落使用 text-align: justify 时,最后一行的文字往往较短,默认左对齐。text-align-last 可单独控制最后一行的对齐方式。

1
2
3
4
p {
text-align: justify;
text-align-last: center; /* 最后一行居中显示 */
}

3.3 vertical-align:垂直对齐

vertical-align 控制行内元素表格单元格垂直方向上的对齐方式。注意:它不能直接用于块级元素来实现垂直居中。

常用值(行内场景):

说明
baseline 默认值。元素基线对齐父元素基线。
top 元素顶部对齐行盒顶部。
middle 元素垂直中点对齐父元素基线 + x-height 的一半。
bottom 元素底部对齐行盒底部。
sub 下标对齐。
super 上标对齐。
数值(px/em 正值上升,负值下降。相对于基线偏移。

常见场景:消除图片底部的空白间隙。

1
2
3
<div style="border: 1px solid #ccc;">
<img src="photo.jpg" style="width: 100px;">
</div>

图片默认按基线对齐,基线下方会留出空隙(为字体下伸部预留的空间)。解决方案:

1
2
3
4
5
6
7
img {
vertical-align: middle; /* 或 top、bottom */
}
/* 或者 */
img {
display: block;
}

4. line-height:行高与行盒

line-height 是排版中最核心的属性之一。它定义了一行文字的最小高度(更准确地说,是行盒的高度),直接影响文字的可读性和垂直间距。

4.1 五种取值类型

取值 示例 计算方式 推荐度
normal line-height: normal; 浏览器默认值(通常约 1.2,取决于字体和浏览器)。 不推荐(不可控)。
纯数值 line-height: 1.5; 元素自身 font-size × 数值。子元素继承此数值(非计算值)。 最推荐
长度值 line-height: 24px; 固定像素值。 不推荐(不同字号会冲突)。
百分比 line-height: 150%; 相对于父元素font-size 计算后,将计算值继承给子元素。 不推荐(易导致子元素行高异常)。
em line-height: 1.5em; 相对于父元素font-size,行为与百分比相同。 不推荐(同百分比)。

4.2 纯数值为何最优:继承行为的差异

这是 line-height 最经典的知识点。

1
2
3
4
5
6
<div style="font-size: 20px; line-height: 1.5;">
父元素文字
<p style="font-size: 40px;">
子元素文字
</p>
</div>
line-height 父元素行高 子元素继承到的是 子元素实际行高 效果
1.5(纯数值) 20 × 1.5 = 30px 数值 1.5 40 × 1.5 = 60px ✅ 子元素自适应
150% 20 × 150% = 30px 计算值 30px 30px ❌ 子元素行高太小,文字重叠
1.5em 20 × 1.5 = 30px 计算值 30px 30px ❌ 同百分比

结论:始终使用无单位的纯数值(如 1.51.6)设置 line-height。子元素会继承这个数值并根据自己的字号重新计算,保证行高始终与字号成比例。

4.3 line-height 的垂直居中原理

单行文字在容器内垂直居中,常见做法是将 line-height 设置为容器高度。

1
2
3
4
5
.button {
height: 48px;
line-height: 48px; /* 行高 = 容器高 → 文字垂直居中 */
text-align: center;
}

原理:文字在行盒内始终垂直居中。当行盒高度等于容器高度时,文字自然居中。此方法仅对单行文字可靠,多行文字需使用 Flexbox。


5. white-space 与空白处理

white-space 控制元素内空白字符(空格、换行符、制表符)的处理方式。它是 white-space-collapsetext-wrap 两个属性的简写。

空白折叠 自动换行 等效于(新语法) 典型场景
normal 折叠 换行 white-space-collapse: collapse; text-wrap: wrap; 默认行为。
nowrap 折叠 不换行 文本强制不换行。 表格表头不换行、水平导航栏。
pre 保留 不换行 行为同 <pre> 标签。 展示代码块、ASCII 艺术。
pre-wrap 保留 换行 保留空格和换行,但允许自动换行。 用户输入的多行文本展示。
pre-line 折叠 换行 折叠连续空格,但保留显式换行符。 保留诗歌或地址的换行格式。
break-spaces 保留 换行 pre-wrap 类似,但允许在保留的空格内断行。 超长连续空格也能换行。
1
2
3
4
.code-block {
white-space: pre-wrap; /* 保留格式但自动换行 */
font-family: monospace;
}

6. word-breakoverflow-wrap:断词与溢出控制

当文本内容超出容器宽度时,这两个属性控制如何断行。

6.1 overflow-wrap

控制当一个单词过长无法放入一行时,是否在单词内部强制断行。

说明
normal 默认。仅在半角空格或连字符处断行。过长的单词会溢出容器。
break-word 若整个单词都放不下,则在单词内部任意字符处断行。优先尝试不破坏单词,实在放不下才强制断开。
anywhere break-word 类似,但断行更积极——在计算最小内容尺寸时也允许断词。

6.2 word-break

控制单词内部的断行规则,对所有文本生效(不仅限于溢出容器的情况)。

说明
normal 默认。根据语言规则在合适位置断行(CJK 文本可在任意字符间断行)。
break-all 任意字符之间都可断行。即使是英文单词,也可在任意字母间断开。
keep-all 尽量不断词。CJK 文本不会在字符间随意断行,仅在空格或连字符处断行。英文单词内部不断行。

6.3 文本溢出省略号

单行文本溢出时显示省略号(...)是极常见的 UI 需求,需要三个属性协同作用:

1
2
3
4
5
.ellipsis {
white-space: nowrap; /* 强制单行 */
overflow: hidden; /* 溢出隐藏 */
text-overflow: ellipsis; /* 溢出部分显示省略号 */
}

多行文本溢出省略(兼容性稍差):

1
2
3
4
5
6
.line-clamp-3 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3; /* 限制显示 3 行 */
overflow: hidden;
}

课后练习

一、概念自测(选择题 / 填空题)

  1. (单选) 关于 line-height 的取值,以下哪个是最推荐的做法?
    A. line-height: 24px;
    B. line-height: 150%;
    C. line-height: 1.5;
    D. line-height: 1.5em;

  2. (单选) 关于 @font-face 中的 font-display 属性,以下哪个值可以确保文字在字体加载期间始终可见,并在字体加载完成后平滑切换
    A. block
    B. swap
    C. fallback
    D. auto

  3. (填空) 要实现单行文本溢出时显示省略号,需要同时设置三个属性:white-space: nowrapoverflow: hidden______

  4. (多选) 以下哪些 CSS 属性可以用于消除 <img> 底部与父容器之间的空白间隙?
    A. display: block
    B. vertical-align: middle
    C. line-height: 0
    D. float: left

二、AI 编程任务:编写面向 AI 的提示词

场景:你需要为一个新闻阅读应用设计正文排版样式。要求如下:

  • 使用自定义字体 "Noto Serif SC"(一种中文衬线字体),通过 @font-face 加载 woff2 格式,并设置 font-display: swap
  • 全局根字号 18px,正文使用 1rem
  • 正文 line-height 设置为 1.8,段落之间间距 1.2em
  • 标题使用 2 倍根字号,加粗 700,line-height1.3
  • 代码块使用等宽字体,背景色 #f5f5f5white-space: pre-wrap 保留格式但允许换行。
  • 链接文字颜色为 #0066cc,并在悬停时添加下划线。
  • 文章卡片中的摘要文字限制显示 2 行,溢出显示省略号。

任务要求:请写出一段完整的中文提示词,发送给 AI,使其生成完整的 HTML 和 CSS 排版代码。提示词中应明确指定字体加载策略、字号和行高的单位选择理由、以及多行省略的技术方案。

三、面试真题与参考答案

题目(京东前端面试题):

请详细解释 line-height 取值为纯数值(如 1.5)、百分比(如 150%)、em 单位(如 1.5em)时,在继承行为上有何差异?请用具体代码示例说明哪种方式是最佳实践,并解释原因。

参考答案

1. 继承行为的核心差异

  • 纯数值(如 line-height: 1.5):子元素继承的是这个数值本身1.5),然后乘以子元素自己的 font-size 得到实际行高。每个元素的行高与其自身字号成比例。
  • 百分比(如 line-height: 150%):先基于父元素的 font-size 计算出一个具体的像素值,子元素继承的是这个计算后的固定值。子元素无论字号多大,都使用这个固定的行高。
  • em 单位(如 line-height: 1.5em):行为与百分比完全一致——先基于父元素字号计算为像素值,再将固定值传给子元素。

2. 代码示例

1
2
3
4
5
6
7
.parent { font-size: 20px; line-height: 1.5; }
.child { font-size: 40px; }
/* 子元素实际行高 = 40 × 1.5 = 60px → 比例协调 */

.parent { font-size: 20px; line-height: 150%; }
.child { font-size: 40px; }
/* 父元素计算值 = 20 × 150% = 30px,子元素继承 30px → 文字重叠 */

3. 最佳实践与原因
始终使用无单位的纯数值。原因在于:

  • 行高与字号保持恒定比例,任何嵌套深度的元素都能根据自身字号正确计算。
  • 避免因子元素字号变化导致的文字重叠或间距过大的问题。
  • 维护方便——修改根字号时,全局行高比例自动适配,无需逐一调整。

课后练习答案

一、概念自测答案

  1. C

    • 解析:纯数值 1.5 在继承时保留数值而非计算值,子元素根据自身字号重新计算,是最灵活、最不易出错的做法。
  2. B

    • 解析:swap 策略立即显示后备字体,加载完成后平滑切换,用户始终能看到文字。
  3. text-overflow: ellipsis

    • 解析:这三个属性必须同时设置才能实现单行文本溢出省略号效果。
  4. A、B、C、D

    • 解析:display: block 将图片变为块级,消除行内基线空隙;vertical-align: middle/top 改变基线对齐方式;line-height: 0 消除行盒高度;float 使图片脱离正常流。均可消除底部空白间隙。

二、AI 编程任务参考答案(提示词示例)

示例提示词
“请为一个新闻阅读应用生成完整的排版样式(HTML + CSS)。要求:

  • 使用 @font-face 加载自定义字体 Noto Serif SC,格式 woff2,设置 font-display: swap
  • <html> 根字号设为 18px,正文字体使用 1rem
  • 正文 line-height: 1.8,段落 pmargin-bottom: 1.2em
  • 标题 h1 字号 2remfont-weight: 700line-height: 1.3
  • 代码块 <pre><code> 使用等宽字体族('Fira Code', 'Consolas', monospace),背景 #f5f5f5white-space: pre-wrap,内边距 16px,圆角 8px
  • 链接 a 颜色 #0066cc,无下划线;悬停时显示下划线。
  • 文章摘要卡片 .summary 使用多行截断(-webkit-line-clamp: 2)并显示省略号。
  • 请解释为何 line-height 使用纯数值而非百分比。直接输出完整 HTML 文件。”
CATALOG
  1. 1. 第21课:字体与文本样式
    1. 1.1. 1. 字体属性:控制字符的形态
      1. 1.1.1. 1.1 font-family:字体族系与后备字体栈
      2. 1.1.2. 1.2 font-size:字号与单位
      3. 1.1.3. 1.3 font-weight:字重(粗细)
      4. 1.1.4. 1.4 font-style:斜体与伪斜体
      5. 1.1.5. 1.5 font 简写属性
    2. 1.2. 2. @font-face:加载自定义 Web 字体
      1. 1.2.1. 2.1 src 与字体格式
      2. 1.2.2. 2.2 font-display:字体加载策略
      3. 1.2.3. 2.3 多字重与多风格的加载
    3. 1.3. 3. 文本样式属性:控制排列与对齐
      1. 1.3.1. 3.1 text-align:水平对齐
      2. 1.3.2. 3.2 text-align-last:最后一行的对齐方式
      3. 1.3.3. 3.3 vertical-align:垂直对齐
    4. 1.4. 4. line-height:行高与行盒
      1. 1.4.1. 4.1 五种取值类型
      2. 1.4.2. 4.2 纯数值为何最优:继承行为的差异
      3. 1.4.3. 4.3 line-height 的垂直居中原理
    5. 1.5. 5. white-space 与空白处理
    6. 1.6. 6. word-break 与 overflow-wrap:断词与溢出控制
      1. 1.6.1. 6.1 overflow-wrap
      2. 1.6.2. 6.2 word-break
      3. 1.6.3. 6.3 文本溢出省略号
    7. 1.7. 课后练习
      1. 1.7.1. 一、概念自测(选择题 / 填空题)
      2. 1.7.2. 二、AI 编程任务:编写面向 AI 的提示词
      3. 1.7.3. 三、面试真题与参考答案
    8. 1.8. 课后练习答案
      1. 1.8.1. 一、概念自测答案
      2. 1.8.2. 二、AI 编程任务参考答案(提示词示例)