Overview
The CSS box model represents the space occupied by an element and consists of four areas: margin, border, padding, and content region (width and height). The image below shows a block element with a 10px margin, 20px border, 30px padding and a width and height of 100px. The resulting box height and width is 220px by 220px.
![](img/box-model.png)
Although most HTML elements have these properties, it's important to note that setting one doesn't always mean that it will render in the way shown above. For example, a margin edge can be collapsed, overlapped or transferred to another element. Many examples in this lab will show that setting the top-edge of a margin will sometimes cause it to be transferred to the top-edge of an ancestor.
This is a common theme in CSS. Setting a value will sometimes have only a partial effect or affect a different element altogether or have no affect at all (e.g., setting the opacity to 1 can have no affect but setting it to 0.6 can, but instead of appearing as 0.6 it may appear as 0.3 - see Irreversible Opacity).
Shared CSS
This section defines styles shared by all experiments on this page. Each class uses the default static position. Since position can't be inherited, the position remains static unless explicitly set. Also, there is no margin or padding used, except for extension classes (e.g., the "with-margin" class). These styles will often be applied to three nested divs: outermost, which contains middleGrid, which in turn contains innermost.
Basic Margin and Position
This section consists of basic experiments where setting the margin on an element affects only that element and not a different element (or both).
Absolute in Static
Innermost is given a 20px margin. Since it's an absolute-positioned div inside a static one, the results are as expected: There's a 20px margin all around, with no side-effects.
MiddleGrid was not given a margin, since it's a static div nested inside a static div. Adding a margin would trigger the Vertical Margin Transfer effect.
Static in Absolute
Innermost is given a 20px margin. Since it's a static-positioned div inside an absolute one, the results are as expected: There's a 20px margin all around, with no side-effects.
MiddleGrid has been given a 10px margin. Since it's an absolute div nested inside a static one, the results are also as expected: 10px margin all around, with no side-effects.
Absolute in Relative
Innermost is given a 20px margin. Since it's an absolute-positioned div inside a relative div, the results are the expected 20px margin all around, with no side-effects.
MiddleGrid was not given a margin. Since it's a relative div nested inside a static one, adding a margin would result in the Vertical Margin Transfer effect.
Relative in Absolute
Innermost is given a 20px margin. Since it's a relative-positioned div inside an absolute one, the results are as expected: 20px margin all around, with no side-effects.
MiddleGrid was given a 10px margin. Since it's an absolute div nested inside a static one, the results are also as expected: 10px margin all around, with no side-effects.
Absolute in Absolute
Innermost is given a 20px margin. Since it's an absolute-positioned div inside an absolute div, the results are the expected 20px margin all around, with no side-effects.
MiddleGrid was given a 10px margin. Since it's an absolute div nested inside a static one, the results are also as expected: 10px margin all around, with no side-effects.
Margin Caveats
The margin of a block-level element can collapse, overlap or be transferred to another element, depending on a variety of circumstances. This section experiments with some of these effects.
Vertical Margin Transfer (VMT)
When a static or relative-positioned block-level element is nested inside of a static or relative-positioned parent, its top and bottom margins may be transferred up the hierarchy until a suitable ancestor is found. This is true for blocks of static elements nested in static elements, relative nested in static, static nested in relative and relative nested in relative.
For example, the experiment below uses a relatively positioned innermost div with a 20px margin, nested inside of a single statically positioned ancestor div. As expected, this pushes the innermost div 20px to the right, relative to its parent, outermost div.
Surprisingly, the top and bottom margins have no effect on the innermost div's distance from the top of outermost. Instead, the top and bottom margins bypasses the innermost div and are directly transferred to the top of the outermost div, pushing it down by 20px (as evidenced by the more than 20px gap above outermost) as well as pushing the display wrapper down at the bottom.
Top Margin Transfer
This experiment highlights the affect of Vertical Margin Transfer on the top margin (using the same div structure as most of the other examples on this page). The bottom margin is not affected in this scenario, because the content height of the ancestor divs are explicitly set.
As can be seen in the Rendered Result, the 20px margin defined by the with-margin class and provided to the innermost div, has been transferred to the top of the outermost div (as evidenced by the more than 20px gap above outermost).
Content Workaround for VMT
Padding Workaround for VMT
Border Workaround for VMT
Border
TODO
Padding
TODO
Vertical Centering
Multiple Inner Boxes
This series of experiments shows how multiple inner boxes behave in the box model.
Multiple Absolute Inner Boxes
Multiple Static Inner Boxes
The following behaviours of the innermost boxes can be observed:
- Block elements flow vertically.
- A block element that doesn't set a width, will stretch horizontally to fill the space of its parent container (e.g., middleGrid).
- A block element that doesn't set a height, will stretch vertically to accommodate the space required by its children.
- Margins can overlap. For example, the top margin of a block element can overlap the bottom margin of a sibling block above it. As shown below,the top of the box with "Margins will Overlap", overlaps the bottom margin of the box above it (as evidenced by the 20px gap between them, instead of the expected 40px gap).
- Using margin:auto, causes the horizontal margins to fill the empty space, which horizontally centers the div.
- Using display:inline-block, causes a block element to be rendered as a block element, but flow as if it were an inline element.