Margin-top 为百分比时为什么是以父元素的宽度计算而不是高度?

先说一个有意思的事情,在一个国外对前端工程师的测试里,问给子元素设置 margin-top 是 10%,请问是谁的 10%?选项有

  1. 父元素的宽度
  2. 父元素的高度
  3. 子元素的宽度
  4. 子元素的高度

结果只有 13% 的人答对,答错的不乏 Google 的前端工程师之类……为什么大部分人都打错了,我想是因为 W3C 的定义,的确是很违背正常人的『直觉』啊:

The percentage is calculated with respect to the width of the generated box’s containing block. Note that this is true for margin-top and margin-bottom as well.

让我们再回到标题里的问题……当然,还有 margin-bottom 和 padding-top/bottom 也这样,看起来这有点反正常认知不是吗,为什么某个块元素的 height 值为百分比的时候就是以父元素的高度来计算,但同样为定义垂直距离的 margin/padding-top/bottom 却是按父元素宽度呢?

网上对此有很多讨论,一种说法是:当使用类似 margin: 20% 这样的简写的时候,为了不造成歧义,所以干脆就将定义垂直距离的 margin/padding-top/bottom 也都按父元素的宽度计算。我觉得能想到这种说法的人也真是太有才了……看起来貌似还是有点道理的,但就 margin: 20% 这样的写法,如果 top/bottom 和 left/right 走不一样的基数,left/right 按父元素宽度算,top/bottom 按父元素高度算,其实也没那么不好接受吧。

第二种说法是:因为父元素的高度往往由子元素来决定,所以如果 margin/padding-top/bottom 按照父元素高度来决定,容易造成高度计算逻辑混乱,什么意思呢?

网页宽度默认就是窗口的宽度,但是高度并不是窗口的高度,而是看网页的内容的多少来决定网页的高度,这也是为什么给 body > div 设定 height: 100% 是没有任何效果的,除非给 html 和 body 都设置了 height:100% 的高度:

但很少情况我们会给一个元素设置高度,而是让元素随内容的增加而增加。如果子元素的内容确定,高度也就确定,假如是 child_height,那么父元素的高度,在子元素没有任何 margin 和 padding 的情况下,也确定了,就是 parent_height = child_height(content-box)。假如子元素的 margin-top 和 padding-top 是按父元素的高度计算的,设置子元素的 padding-top/bottom 高度是 10%,那么父元素的高度变成了 parent_height = parent_height * 20% + child_height,但注意,因为父元素变高了,所以之前算出来的父元素的 20% 的高度,实际上又不是现在父元素的高度的 20% ……。

这个说法一开始我觉得好有道理,但总觉得还是哪儿有点不对。如果子元素的高度已经得到,且子元素的 margin-top/bottom 已经给定,父元素的高度其实也是可以确定吧……换种说法可能大家都明白了:设父元素高度为 x,子元素高度为 y,子元素的 margin-top/bottom 都为 n%,由此可得 x * 2 * n% + y = x,求 x = ?

无论是因为 margin/padding 的缩写会导致理解歧义也好,还是因为按高度算百分比难以理解也好,总之,W3C 就是这么规定的……另外如果 writing-mode 属性改成横向的,margin 和 padding 的所有计算基准就都变成按父元素高度来计算了,可能 W3C 觉得按一个可预期可固定的值来做基数比较好吧。

wx pay

CC BY-NC-ND 4.0 Margin-top 为百分比时为什么是以父元素的宽度计算而不是高度? by Chrisyue's Blog is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

发表评论

电子邮件地址不会被公开。

sixty four − 57 =