According to this answer https://stackoverflow.com/a/2680515/1518921
In accordance with W3 Collapsing Margins:
The adjacent margins of two or more boxes (which may or may not be siblings) can combine to form a single margin. Refers to this type of margins that combine in this way as "collapse" and the resulting combined margin is called "collapse margin".
This is also explained https://www.w3.org/TR/CSS2/visuren.html#block-formatting:
Elements with float, Absolute and elements with inline-block, table-Cell, and table-captions for example are not really block boxes and block boxes with overflow other than overflow: visibile
generate a new block for content formatting.
In the context of a block of content formatting, the "boxes" are placed vertically out one after the other, starting from the top of the contents of a block. The vertical distance between the boxes is determined by the property margin
, the vertical margins between the level of the blocks are adjacent in the context formatting causing the collapse.
When there is no collapse (mixing of the margins):
- Horizontal margins.
- Elements with overflow that is different from Visible, such as Hidden and auto
- Elements with
float: left;
or float: right;
- Elements with
position
other than static
Note: I still want to improve the answer, because my English is a little weak and sometimes I get lost in the sense of the phrase, outside the cited links are outdate, I’m seeing more updated sources
How to avoid collapse
So that the margin does not affect the parent element you can apply a padding-top
(use margin-top
in the child element) and padding-bottom
(use margin-bottom
in the child element) in the parent element so it is corrected automatically:
.pai1 {
background: #f00;
color: #fff;
}
.pai2 {
padding: 1px 0; /* adiciona um px no topo e em baixo */
margin: -1px 0; /* ajusta negativamente para que o padding aparente sumir */
background: #00f;
color: #fff;
}
.pai1 .filho, .pai2 .filho {
margin: 20px 0;
}
<p>Teste</p>
<!-- com o problema -->
<div class="pai1">
<div class="filho">teste</div>
</div>
<hr>
<!-- sem o problema -->
<div class="pai2">
<div class="filho">teste</div>
</div>
Using the pseudo element :before
and :after
:
.pai {
background: #f00;
color: #fff;
}
.pai:before, .pai:after {
content: " ";
height: 0;
display: block;
overflow: hidden;
}
.pai .filho {
margin: 20px 0;
}
<p>Teste</p>
<div class="pai">
<div class="filho">teste</div>
</div>
Using overflow: hidden;
(this chance does not have fixed height), this is perhaps the simplest way to solve:
.pai {
background: #f00;
color: #fff;
overflow: hidden;
}
.pai .filho {
margin: 20px 0;
}
<p>Teste</p>
<div class="pai">
<div class="filho">teste</div>
</div>
margin-top in all browsers for some reason comes even from the parent element or even from above elements, I know I’ve read about it somewhere, I’ll see
– Guilherme Nascimento