From 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:
..
- 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:
- 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.
- Otherwise, the containing block is formed by the padding edge of the ancestor.
So the position:absolute
element will use 400px
that include the padding
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.
The other one will use the content-box which is 400px - 20px
so you won't have the same height
400*0.8 = 320 [positionned element]
(400 - 20)*0.8 = 304 [non-positionned element]
This is somehow logical since padding is a way to create space so it will get removed from the calculation when considering non-positionned elements. This logic is different for positionned element.
An example to illustrate:
.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>
When it comes to position it's a different story. Below a related question to understand how the elements is positionned if you don't set top/left/right/bottom and you will see that padding will play a role here:
Why aren't my absolutely/fixed-positioned elements located where I expect?
If you don't set box-sizing:border-box
, the logic will remain the same but the values will change.
From the specification related to the default value 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.
The calculation will become
(400 + 20)*0.8 = 336 [positionned element]
400*0.8 = 320 [non-positionned element]
If you want them to have the same size you need to define the height differently for the absolute 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>
Or don't use 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>