Probably this is very stupid and well-known trick, but I haven't found any fix yet. I've tried "overflow
", "content: ' '; display: table;
", padding
and 1px
border
. No success. So I've made small example to this problem.
There are 2 block elements: header with bottom margin and footer with top margin. The task is to make margins add together: 50 + 49 = 99 px!
.main-header {
margin-bottom: 50px;
}
.main-footer {
margin-top: 49px;
}
<h1>if distance btw H.&F. is 99 px then margins don't collapse! Unfortunatelly, is is</h1>
<header class="main-header">
HEADER Lorem ipsum dolor.
</header>
<footer class="main-footer">
FOOTER <span>©2015 Lorem ipsum dolor.</span>
</footer>
You could use Flexbox because it doesn't have collapsing margins
.
.content {
display: flex;
flex-direction: column;
}
.main-header {
margin-bottom: 50px;
}
.main-footer {
margin-top: 49px;
}
<div class="content">
<header class="main-header">
HEADER Lorem ipsum dolor.
</header>
<footer class="main-footer">
FOOTER <span>©2015 Lorem ipsum dolor.</span>
</footer>
</div>
You can float them to disable the collapsing margins, with width:100%
to make them to occupy the entire width, rather than determined by the content.
.main-header,
.main-footer {
float: left;
width: 100%;
}
.main-header {
margin-bottom: 50px;
}
.main-footer {
margin-top: 49px;
}
<h1>if distance btw H.&F. is 99 px then margins don't collapse! Unfortunatelly, is is</h1>
<header class="main-header">
HEADER Lorem ipsum dolor.
</header>
<footer class="main-footer">
FOOTER <span>©2015 Lorem ipsum dolor.</span>
</footer>
To start, the flexbox solution that @Nenad Vracar posted is the most valid one.
A couple of alternatives
Assuming the problem is that you do not know if there is something between the two tags you could use an extra selector for this case (although it would fail if only text is between the two tags as it would still apply the 99 margin)
.main-header + .main-footer{margin-top:99px;}
<h1>if distance btw H.&F. is 99 px then margins don't collapse! Unfortunatelly, is is</h1>
<header class="main-header">
HEADER Lorem ipsum dolor.
</header>
<footer class="main-footer">
FOOTER <span>©2015 Lorem ipsum dolor.</span>
</footer>
Now, depending on your situation you could use the tricks you mention and pass the margin to the pseudo-elements.
.main-header:after {
content: '';
margin-bottom: 50px;
display: table;
}
.main-footer:before {
content: '';
display: table;
margin-top: 49px;
}
.main-header,
.main-footer {
overflow: auto;
}
<h1>if distance btw H.&F. is 99 px then margins don't collapse! Unfortunatelly, is is</h1>
<header class="main-header">
HEADER Lorem ipsum dolor.
</header>
<footer class="main-footer">
FOOTER <span>©2015 Lorem ipsum dolor.</span>
</footer>
As there's adjacent siblings and since the margin collapse takes the higher margin, we make use of the +
CSS operator so that when there's no other elements between header
and footer
, we increase the margin-top
of the footer
to 99px
JS Fiddle
.main-header {
margin-bottom: 50px;
background-color: orange;
}
.main-footer {
background-color: skyblue;
margin-top: 49px;
}
.main-header + .main-footer {
/* only when there's no other elements between header and footer this will be applied */
margin-top: 99px;
}
<header class="main-header">HEADER Lorem ipsum dolor.</header>
<footer class="main-footer">FOOTER <span>©2015 Lorem ipsum dolor.</span></footer>
You could add a simple float
and clear:both
, use ::before
and ::after
pseudo elements.
As per MDN:
Margin collapsing occurs in three basic cases:
Adjacent siblings
The margins of adjacent siblings are collapsed (except when the later sibling needs to be cleared past floats).
.main-header::after, .main-footer::before {
content:'';
float:left;
width:100%;
clear:both;
}
.main-header::after {
margin-bottom: 50px;
}
.main-footer::before {
margin-top: 49px;
}
<header class="main-header">
HEADER Lorem ipsum dolor.
</header>
<footer class="main-footer">
FOOTER <span>©2015 Lorem ipsum dolor.</span>
</footer>