Reputation: 35301
Is there a way to disable margin-collapsing altogether? The only solutions I've found (by the name of "uncollapsing") entail using a 1px border or 1px padding. I find this unacceptable: the extraneous pixel complicates calculations for no good reason. Is there a more reasonable way to disable this margin-collapsing?
Upvotes: 285
Views: 177186
Reputation: 1158
There are two main types of margin collapse:
Using a padding or border will prevent collapse only in the latter case. Also, any value of overflow
different from its default (visible
) applied to the parent will prevent collapse. Thus, both overflow: auto
and overflow: hidden
will have the same effect. Perhaps the only difference when using hidden
is the unintended consequence of hiding content if the parent has a fixed height.
Other properties that, once applied to the parent, can help fix this behaviour are:
float: left / right
position: absolute
display: flex / grid
You can test all of them here: http://jsfiddle.net/XB9wX/1/.
I should add that, as usual, Internet Explorer is the exception. More specifically, in IE 7 margins do not collapse when some kind of layout is specified for the parent element, such as width
.
Sources: Sitepoint's article Collapsing Margins
Upvotes: 354
Reputation: 1382
CSS* | Fixes |
---|---|
display: flow-root; |
✅ Parent element collapse ❌ Sibling element collapse |
display: flex; |
✅ Parent element collapse ✅ Sibling element collapse |
*Modern browsers (excluding IE11) support display: flow-root
and display: flex
.
section {
background: green;
outline: 2px solid purple;
}
p {
background: yellow;
margin: 1em 0;
}
section.flow-root {
display: flow-root;
}
section.flex {
display: flex;
flex-direction: column;
}
<h2>Default</h2>
<section>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</section>
<h2><code>flow-root</code> (Fixes only container)</h2>
<section class="flow-root">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</section>
<h2><code>flex</code> (Fixes both container & siblings)</h2>
<section class="flex">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</section>
Upvotes: 15
Reputation: 31
Try
{
display:flex;
flex-direction:column;
}
or
{
display:grid;
}
Upvotes: 3
Reputation: 49180
To prevent margin collapsing between siblings, add display: inline-block;
to one of the siblings (one is enough though you can add it to both).
Upvotes: 3
Reputation: 810
You can also use the good old micro clearfix for this.
#container::before, #container::after{
content: ' ';
display: table;
}
See updated fiddle: http://jsfiddle.net/XB9wX/97/
Upvotes: 71
Reputation: 587
Every webkit based browser should support the properties -webkit-margin-collapse
. There are also subproperties to only set it for the top or bottom margin. You can give it the values collapse (default), discard (sets margin to 0 if there is a neighboring margin), and separate (prevents margin collapse).
I've tested that this works on 2014 versions of Chrome and Safari. Unfortunately, I don't think this would be supported in IE because it's not based on webkit.
Read Apple's Safari CSS Reference for a full explanation.
If you check Mozilla's CSS webkit extensions page, they list these properties as proprietary and recommend not to use them. This is because they're likely not going to go into standard CSS anytime soon and only webkit based browsers will support them.
Upvotes: 8
Reputation: 8301
One neat trick to disable margin collapsing that has no visual impact, as far as I know, is setting the padding of the parent to 0.05px
:
.parentClass {
padding: 0.05px;
}
The padding is no longer 0 so collapsing won't occur anymore but at the same time the padding is small enough that visually it will round down to 0.
If some other padding is desired, then apply padding only to the "direction" in which margin collapsing is not desired, for example padding-top: 0.05px;
.
Working example:
.noCollapse {
padding: 0.05px;
}
.parent {
background-color: red;
width: 150px;
}
.children {
margin-top: 50px;
background-color: lime;
width: 100px;
height: 100px;
}
<h3>Border collapsing</h3>
<div class="parent">
<div class="children">
</div>
</div>
<h3>No border collapsing</h3>
<div class="parent noCollapse">
<div class="children">
</div>
</div>
Edit: changed the value from 0.1
to 0.05
. As Chris Morgan mentioned in a comment bellow, and from this small test, it seems that indeed Firefox takes the 0.1px
padding into consideration. Though, 0.05px
seemes to do the trick.
Upvotes: 83
Reputation: 461
Actually, there is one that works flawlessly:
display: flex; flex-direction: column;
as long as you can live with supporting only IE10 and up
.container {
display: flex;
flex-direction: column;
background: #ddd;
width: 15em;
}
.square {
margin: 15px;
height: 3em;
background: yellow;
}
<div class="container">
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
</div>
<div class="container">
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
</div>
Upvotes: 31
Reputation: 32716
For your information you could use grid but with side effects :)
.parent {
display: grid
}
Upvotes: 0
Reputation: 12218
I had similar problem with margin collapse because of parent having position
set to relative. Here are list of commands you can use to disable margin collapsing.
Just try to assign any parent-fix*
class to div.container
element, or any class children-fix*
to div.margin
. Pick the one that fits your needs best.
When
div.absolute
with red background will be positioned at the very top of the page.div.absolute
will be positioned at the same Y coordinate as div.margin
html, body { margin: 0; padding: 0; }
.container {
width: 100%;
position: relative;
}
.absolute {
position: absolute;
top: 0;
left: 50px;
right: 50px;
height: 100px;
border: 5px solid #F00;
background-color: rgba(255, 0, 0, 0.5);
}
.margin {
width: 100%;
height: 20px;
background-color: #444;
margin-top: 50px;
color: #FFF;
}
/* Here are some examples on how to disable margin
collapsing from within parent (.container) */
.parent-fix1 { padding-top: 1px; }
.parent-fix2 { border: 1px solid rgba(0,0,0, 0);}
.parent-fix3 { overflow: auto;}
.parent-fix4 { float: left;}
.parent-fix5 { display: inline-block; }
.parent-fix6 { position: absolute; }
.parent-fix7 { display: flex; }
.parent-fix8 { -webkit-margin-collapse: separate; }
.parent-fix9:before { content: ' '; display: table; }
/* Here are some examples on how to disable margin
collapsing from within children (.margin) */
.children-fix1 { float: left; }
.children-fix2 { display: inline-block; }
<div class="container parent-fix1">
<div class="margin children-fix">margin</div>
<div class="absolute"></div>
</div>
Here is jsFiddle with example you can edit
Upvotes: 2
Reputation: 146
I know that this is a very old post but just wanted to say that using flexbox on a parent element would disable margin collapsing for its child elements.
Upvotes: 9
Reputation: 4888
overflow:hidden
prevents collapsing margins but it's not free of side effects - namely it... hides overflow.
Apart form this and what you've mentioned you just have to learn live with it and learn for this day when they are actually useful (comes every 3 to 5 years).
Upvotes: 24