<div class="container">
<div class="parent">
<div class="child"></div>
</div>
</div>
<style>
.container {
width: 500px;
height: 500px;
background: lightblue;
position: relative;
}
.parent {
width: 300px;
height: 300px;
border: 5px solid #000;
margin-left: 100px;
transform: rotate(0deg);
}
.child {
width: 100px;
height: 100px;
position: absolute;
background: red;
left: 20px;
top: 20px;
}
</style>
In this structure, the child element with absolute positioning doesn't position itself relative to the grandparent container as one might expect, but rather to its immediate parent. This behavior stems from CSS containing block rules.
Containing Block Fundamentals
A containing block establishes the coordinate system for:
- Percentage-based width/height calculations
- Positioning of absolute/fixed-positioned elements
- Padding and margin percentage values
Containing Block Types
1. Initial Containing Block
The root element (<html>) establishes the initial containing block, which is viewport-sized and positioned at the canvas origin (top-left corner).
2. Element Containing Blocks
For non-root elements, the containing block depends on positioning:
Static/Relative Positioning
The containing block is the nearest block container's content area.
Fixed Positioning
The viewport establishes the containing block.
Absolute Positioning
The containing block is the nearest positioned ancestor (non-static). However, there are exceptions when these properties are present:
- transform/perspective not none
- will-change: transform/perspective
- filter not none (Firefox: will-change: filter)
- contain: paint
This explains why our example's child element positioned relative to its trensformed parent rather than the relatively-positioned grandparent.