CSS 与布局 / Inline 与 inline-block · 拆解 / 替换元素的 baseline:img 撑高 vs input 错位 待审核 4 / 8
替换元素 baseline 谜题

替换元素的 baseline:img 撑高 vs input 错位

<img><input> 都是行内替换元素,默认都按 baseline 对齐——可它们的 baseline 不在同一个地方:<img> 的 baseline 就是它的下外边距边(实测给图加 margin-bottom: 10px,容器从 54px 长到 64px,说明坐在 baseline 上的是 margin 边而非边框底),而 <input> 这类表单控件的 baseline 藏在盒子内部(由 UA 决定,不在底部)。同一条规则、两种 baseline 落点,正好酿成两个经典现象:图片底下凭空多一条缝、inline-block<label><input> 并排却高低错位。本页把这两个 case 并到一起,用真实 getBoundingClientRect() 把各自的 baseline 画出来对照。本页依赖 02 · baseline 与 vertical-align 讲过的对齐规则与 strut 概念。

1 · <img>:baseline = 底边 → 撑高几像素

把图片紧紧包在链接里 <a><img></a>,会发现 <a> 的背景 / 边框比图高出几个像素(line-height: normal 下实测 4px,1.5 下 7px,2 下 11px),底下凭空垫了一条缝。<img> 的下边要坐到这一行的 baseline 上,而行里那个看不见的匿名行内框 / strut 带着 line-height,把字母「g」尾巴垂下去的空间(descent)留在了图的下方。

图 1-1 · 图片底下那条缝的来历:strut 的 descent 与半行距把行框底顶到图片下方。

2 · 为什么会有这条缝

  1. <img> 默认 display: inline,是行内替换元素,默认 vertical-align: baseline——它的下边要坐到这一行的 baseline 上。
  2. 这一行哪怕没有可见文字,也存在一个高度等于 line-heightstrut(匿名行内框的支柱)。它也按 baseline 对齐,但它有自己的下伸部 descent(留给 g、y、p 尾巴的空间)。
  3. strut 的 descent 落在 baseline 下方,于是 line box 的底边被它顶到了图的更下面;<a>(这一行的宿主)只能跟着长高 → 图底下多出那条缝 = 字体的 descent 加半行距,因而随 line-height 增大而变宽。

3 · 三种根治方案(对应上方按钮)

  • **其一,消掉匿名框的高度:**给 <a>line-height: 0;写 font-size: 0 也行,但只在 line-heightnormal 或无单位数字时有效——父级把 line-height 写成长度值时缝仍在(实测 font-size:0; line-height:20px 仍留 10px)。
  • **其二,改对齐方式:**给 <img>vertical-align: top(或 bottom)。不再按 baseline 对齐,自然没有「baseline 之下的 descent」这回事。
  • **其三,让图离开 IFC:**给 <img>display: block。它不再是行内级内容、不参与该 IFC,也就没有行内框对齐问题。代价是 <a> 这类行内元素内含块级盒会被撕成上下两段,背景与边框跟着断开。

注意 vertical-align: middle 不一定清零:它把图中线对到「锚字符 x 的中线」,缝可能变小却未必为 0(还可能上下都留)。要稳定消除,用上面「消匿名框高度 / vertical-align:top / display:block」三种方案。实际项目里图标按钮、轮播图、九宫格布局最常遇到这个问题。

4 · <input> 的 baseline 在内部:老题说的「错位」今天还成立吗

另一道知乎经典问题(貘吃馍香):一个 display: inline-block<label> 和一个 <input> 并排「会错位」。这页不照搬结论,而是用实测验一验——在今天的浏览器里它们到底错不错,以及 <input> 的 baseline 究竟在哪。<input> 是替换元素,它的 baseline 不在盒子底部、而在控件内部(UA 规定);<label> 则用自己末行文字的 baseline。下面 label 用大字号、input 用小字号(故意拉开,看 baseline 怎么对),切 vertical-align 看谁更齐:

图 4-1 · inline-block 的 label 与各类表单控件并排时的对齐情况。

结论与一个反转:<img> 的 baseline 在底边<input> 的 baseline 在盒子内部(实测它盒底没贴 baseline)。也正因为在内部,文本类控件input[type=text]button)与 inline-block 的 label 按默认 baseline 对齐相当整齐;但这不适用于全部控件——实测 checkboxtextarea 的 baseline 就在盒底(textarea 正是因为 overflowvisible 落到那条 fallback 规则上),它们与文本控件并不齐平(Chrome 151,核对于 2026-08)。真把它们拉错位的,往往是改成 vertical-align: top(盒高不同就错)。原问题(2014)的「严重错位」更多是当年各浏览器对替换元素 baseline 实现不一致的产物——见 w3help · RD1016。稳妥做法是用 vertical-align: middleflex

5 · 两类替换元素的 baseline 落点对照

图 5-1 · 同为替换元素,img 与表单控件的 baseline 落点对照。