CSS 基线与 vertical-align
CSS 行内格式化上下文里的基线、line-height、vertical-align 与常见对齐问题的系统梳理。
[!info] related notes
- 所属 MOC: CSS MOC
- 前置概念: 文档流、display 与定位, CSS 文本与视觉样式
- 相关布局: Flex 布局
- 实战问题: 按钮和文字在页面放大比例变化时出现未完全垂直居中情况
CSS 基线与 vertical-align
一句话定义
基线是行内排版里“文字站住的那条参考线”,而 vertical-align 控制的是行内盒在同一行里相对这条线如何对齐。
为什么这个点总让人混乱
因为很多人看到的是“元素没对齐”,但浏览器实际在做的是:
- 先建立行盒
line box - 再根据字体度量、行高、内联盒类型计算基线
- 最后按
vertical-align把每个行内盒摆进这一行
所以按钮、文字、图片、inline-block 看起来没在一条线上,往往不是 Flex 失效,而是行内格式化上下文里的基线规则在起作用。
1. 基线到底是什么
可以先把一行文本想成几条看不见的参考线:
- 顶线:字符可能接近的上边界
- 中线:有些对齐值会参考
- 基线:大多数字符“踩着”的线
- 下延线:
g、p这类字母往下伸出去的区域
对于普通文本,基线最常跟字体度量有关,而不是元素内容框的几何中心。
2. 哪些元素会受基线影响
最典型的是这些:
- 纯文本节点
span这类行内元素inline-blockinline-table- 替换元素,如
img、input
块级元素单独占一行时,通常不直接参与这一层基线对齐。
3. 行内排版时浏览器在算什么
3.1 行盒 line box
同一行里的所有行内内容会被放进一个行盒。这个行盒的高度,通常受以下因素共同影响:
- 字体大小
line-height- 行内盒本身的高度
- 是否有图片、按钮、
inline-block
3.2 文本的基线
普通文字的基线来自字体度量。不同字体、不同字号、不同字重,基线看起来都可能略有差异。
这就是为什么“换了一个特殊字体后突然不对齐”很常见。
3.3 inline-block 的基线
inline-block 的基线不是“盒子垂直中心”。
更接近的理解是:
- 如果它内部有正常行内内容,基线常取最后一行行盒的基线
- 如果没有可参与的行内内容,浏览器会退化到盒子的底边附近来处理
所以两个高度不同的 inline-block,即使都在同一行,也常常视觉上不在中线。
3.4 图片和表单控件
img、input、button 这些替换元素或带默认样式的元素,经常有自己的对齐规则、内边距和默认 line-height,所以最容易把整行的视觉中心拉偏。
4. vertical-align 真正在控制什么
vertical-align 只对以下场景生效:
- 行内级元素
- 表格单元格
它不是通用的“垂直居中大法”,也不会替代 Flex/Grid 对齐。
常见取值可以这样记:
baseline:按基线对齐,默认值middle:元素中线对齐到父行盒基线附近的中线参考,不等于几何绝对居中top/bottom:对齐到当前行盒顶部或底部text-top/text-bottom:更贴近文本字体盒
最常见误区是把 middle 理解成“和旁边元素完全垂直居中”。它只是在行内排版语义里尽量居中,不保证视觉绝对一致。
5. 为什么按钮、文字、图标经常错位
5.1 字体度量不同
同样是 font-size: 16px,不同字体的 x-height、ascender、descender 并不一样,基线自然会偏。
5.2 默认 line-height 和 padding
按钮、输入框常带默认上下内边距和默认行高,而旁边的文字可能只是普通 span。
结果就是:
- 盒子高度不同
- 文字落点不同
- 基线也不同
5.3 inline、inline-block、替换元素混排
这几种盒子的基线规则不完全一样,放在一行里时很容易出现“代码看着都在一行,视觉却不平”的情况。
5.4 缩放和小数像素
浏览器缩放后,字体渲染和像素取整可能产生细微偏移,所以有时 100% 看起来正常,125% 就开始怪。
6. 放到 Flex 里为什么还会出问题
很多人以为:
display: flex;
align-items: center;
就一定彻底解决了。
但 align-items: center 居中的是 flex 项的盒子,不是里面文本的字体度量。
如果子项本身还是按钮、图标、文本混排,内部的:
line-height- 字体
padding- 默认样式
仍然会影响最终视觉中心。
所以常见修正方式是:
- 把按钮本身改成
inline-flex或flex - 统一
font-size和line-height - 减少依赖默认按钮样式
- 用
gap代替相邻元素margin
7. 实战里怎么排查
建议按这个顺序看:
- 看相关元素的
font-size是否一致 - 看
line-height是否一致 - 看按钮/输入框是否带默认
padding、border、appearance - 看元素是
inline、inline-block还是flex - 缩放页面,看是否有小数像素导致的视觉偏移
- 在 DevTools 里临时把按钮改成
inline-flex,观察问题是否立刻消失
8. 更稳的解决策略
方案一:统一文本系统
.label,
.button {
font-size: 14px;
line-height: 1.2;
}
适合纯文本差异导致的错位。
方案二:按钮内部自己做居中
.button {
display: inline-flex;
align-items: center;
justify-content: center;
}
适合按钮和旁边普通文本、图标一起出现的情况。
方案三:必要时显式指定 vertical-align
img,
.icon {
vertical-align: middle;
}
适合图标和文字同行时的细调。
方案四:如果本质是布局问题,就不要继续纠结基线
如果你真正需要的是一组盒子整体居中,优先选:
- Flex
- Grid
不要强行在复杂布局里只靠 vertical-align 硬撑。
9. 面试或笔试怎么答更稳
可以直接这样答:
基线问题本质上是行内排版规则导致的。文字、按钮、图片、
inline-block的基线计算方式不完全一样,再叠加默认line-height、padding和字体度量差异,就会出现看起来不在一条线上的情况。排查时我会先统一字体和行高,再看元素的显示类型;如果是按钮或图标混排,通常会改成inline-flex或显式加vertical-align,而不是只盯着某一个像素去微调。
10. 最短记忆方式
- 基线是文字排版参考线,不是盒子中心线
vertical-align管的是行内对齐,不是万能垂直居中- Flex 居中的是盒子,内部文字是否“看起来居中”还要看字体和行高