负 margin-bottom 为什么把元素「往下推」
经典面试题:三个并排的 inline-block,只给中间那个 margin-bottom: -20px。按直觉「负的下边距」应该把它往上提才对,结果它的边框反而往下沉了 20px。下面这个 lab 用真实
getBoundingClientRect() 把每条关键线画出来,拖滑块逐步拆解。
前提(很重要):三个盒子都设了 overflow: hidden,所以按 02 · baseline 与 vertical-align 讲过的规则,它们的 baseline = 下外边距边(bottom margin edge)。默认 vertical-align: baseline 会把三个盒子的下外边距边对齐到同一条线(绿线)。后面的分析全部围绕这条线展开。
1 · 一步步拆(以 margin-bottom: -20px 为例)
-
对齐的是下外边距边,不是边框底。空 /
overflow:hidden的 inline-block,baseline 就是它的下外边距边。三盒按 baseline 对齐 = 三条下外边距边排到同一条绿线上。 - 负 margin-bottom 把中间盒的「下外边距边」抬高了 20px。
margin-bottom: -20让外边距边跑到边框底之上 20px。 - 为了让外边距边仍落在绿线上,边框只能往下挪 20px。左右两盒的边框底就在绿线上,中间盒的边框底却被挤到绿线下方 20px——这就是看到的「下移」。
-
而 line box 高度保持不变。行框高度按各盒的 margin box 算:中间盒的 margin box 因为
-20正好矮了 20px,顶边没超过左右盒,底边和大家齐平 → 蓝色 line box 高度和没加负 margin 时一样。多出来的那截中间盒边框,是溢出到行框下方的(行框之间不重叠,所以它压住了下一行的位置)。
2 · margin-top 负值:看似「无效」的原因
点上面「改设 margin-top: -20」:中间盒的边框几乎没动。因为对齐基准是下外边距边,而 margin-top 改的是上边——下外边距边没动,盒子坐的位置就没动,边框自然不挪。它只是让 margin box 的顶缩进去 20px(行框可能因此矮一点),所以视觉上「负 margin-top
好像没起作用」。
**归纳:**baseline 对齐 inline-block,锚的是它的下外边距边。动 margin-bottom = 动锚点 → 边框被迫位移(看着「下移 / 上移」);动 margin-top = 不动锚点 → 边框不动(看着「无效」)。