替换元素的 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)留在了图的下方。
2 · 为什么会有这条缝
<img>默认display: inline,是行内替换元素,默认vertical-align: baseline——它的下边要坐到这一行的 baseline 上。- 这一行哪怕没有可见文字,也存在一个高度等于
line-height的 strut(匿名行内框的支柱)。它也按 baseline 对齐,但它有自己的下伸部 descent(留给 g、y、p 尾巴的空间)。 - strut 的 descent 落在 baseline 下方,于是 line box 的底边被它顶到了图的更下面;
<a>(这一行的宿主)只能跟着长高 → 图底下多出那条缝 = 字体的 descent 加半行距,因而随line-height增大而变宽。
3 · 三种根治方案(对应上方按钮)
-
**其一,消掉匿名框的高度:**给
<a>设line-height: 0;写font-size: 0也行,但只在line-height为normal或无单位数字时有效——父级把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 看谁更齐:
结论与一个反转:<img> 的 baseline 在底边、<input> 的 baseline 在盒子内部(实测它盒底没贴 baseline)。也正因为在内部,文本类控件(input[type=text]、button)与
inline-block 的 label 按默认 baseline 对齐相当整齐;但这不适用于全部控件——实测 checkbox 与 textarea 的 baseline 就在盒底(textarea 正是因为 overflow 非 visible 落到那条 fallback
规则上),它们与文本控件并不齐平(Chrome 151,核对于 2026-08)。真把它们拉错位的,往往是改成 vertical-align: top(盒高不同就错)。原问题(2014)的「严重错位」更多是当年各浏览器对替换元素 baseline 实现不一致的产物——见
w3help · RD1016。稳妥做法是用 vertical-align: middle 或 flex。