为什么 padding 会改变 child div 和 border-box 集的高度?

Why does padding change the height of the child div with border-box set?

我有下面这一段html

<div style="position: relative; box-sizing: border-box; width: 400px; height: 400px; padding-top: 20px;">
  <div style="position: absolute; height: 80%; background-color: aqua; width: 100%;"></div>
  <div style="height: 80%; background-color: black; width: 100%;"></div>
</div>

我有一个高度为 400px 的 parent div 和两个 child div,其中每个 child 的高度为 80%。

经过反复试验,我发现 parent div 上的 padding-top: 20px 导致了此问题。

有人可以向我解释为什么会发生这种情况以及如何使 div 大小相同吗?

这似乎在所有主流浏览器中都会发生。

来自 the specification:

The position and size of an element's box(es) are sometimes calculated relative to a certain rectangle, called the containing block of the element. The containing block of an element is defined as follows:

..

  1. If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed', in the following way:
    1. In the case that the ancestor is an inline element, the containing block is the bounding box around the padding boxes of the first and the last inline boxes generated for that element. In CSS 2.1, if the inline element is split across multiple lines, the containing block is undefined.
    2. Otherwise, the containing block is formed by the padding edge of the ancestor.

因此 position:absolute 元素将使用包含 填充

400px

For other elements, if the element's position is 'relative' or 'static', the containing block is formed by the content edge of the nearest block container ancestor box.

另一个将使用 400px - 20px 的内容框,因此您不会有相同的高度

400*0.8 = 320 [positionned element]
(400 - 20)*0.8 = 304 [non-positionned element]

这在某种程度上是合乎逻辑的,因为填充是创建 space 的一种方式,因此在考虑非定位元素时它将从计算中删除。这个逻辑对于 positionned 元素是不同的。

举例说明:

.box {
  border:2px solid;
  padding:20px;
  height:300px;
  width:300px;
  box-sizing:border-box;
  position:relative;
}

.box > div:last-child {
   height:100%;
   width:100%;
   background:red;
}

.box > div:first-child {
   position:absolute;
   width:100%;
   height:100%;
   background:rgba(0,255,0,0.5);
}
<div class="box">
  <div></div>
  <div></div>
</div>


当谈到定位时,情况就不同了。如果您不设置 top/left/right/bottom,请在相关问题下方了解元素的定位方式,您将看到填充将在这里发挥作用:


如果您不设置 box-sizing:border-box,逻辑将保持不变,但值会发生变化。

来自与默认值相关的规范content-box

This is the behavior of width and height as specified by CSS2.1. The specified width and height (and respective min/max properties) apply to the width and height respectively of the content box of the element. The padding and border of the element are laid out and drawn outside the specified width and height.

计算会变成

(400 + 20)*0.8 = 336  [positionned element]
400*0.8 = 320 [non-positionned element]

如果您希望它们具有相同的大小,您需要为绝对元素定义不同的高度:

.box {
  height: calc((100% - 20px)*0.8);
}
/* OR */
.box {
  top:20px;
  bottom: 20%;
}
<div style="position: relative; box-sizing: border-box; width: 400px; height: 400px; padding-top: 20px;">
  <div class="box" style="position: absolute; background-color: aqua; width: 100%;"></div>
  <div style="height: 80%; background-color: black; width: 100%;"></div>
</div>

或者不使用position:absolute

.box {
  box-sizing: border-box;
  width: 400px;
  height: 400px;
  padding-top: 20px;
  
  display: grid;
  grid-template-rows: 80%; /* the height here */
}

.box > * {
  grid-area: 1/1; /* make both elements on top of each other */
}
<div class="box">
  <div style="background-color: black;"></div>
  <div style="background-color: aqua;"></div>
</div>