Vertical margins disappear when parent is set to overflow:visible
It's because of collapsing margins:
If you have overflow: hidden, the margins of the inner div remain inside the outer div.
If you have overflow: visible, the top and bottom margins collpase with the zero margins of the outer div, because they touch each other. This is then recalculated to have the same as the inner margin.
So, overflow: hidden will break collapsing margins with the ones inside. You could break the margin collapsing by giving the outer div a padding or a border. So they won't touch each other and so no collapsing
http://www.howtocreate.co.uk/tutorials/css/margincollapsing
Vertical margins disappear when parent is set to overflow:visible
It's because of collapsing margins:
If you have overflow: hidden, the margins of the inner div remain inside the outer div.
If you have overflow: visible, the top and bottom margins collpase with the zero margins of the outer div, because they touch each other. This is then recalculated to have the same as the inner margin.
So, overflow: hidden will break collapsing margins with the ones inside. You could break the margin collapsing by giving the outer div a padding or a border. So they won't touch each other and so no collapsing
http://www.howtocreate.co.uk/tutorials/css/margincollapsing
Why is this floated div being pulled down by the margin its sibbling?
Give an overflow:hidden
to the parent div, ie .content
margin-top does not work properly
Give an overflow:hidden
to the parent div, ie #first
This happens because of collapsing margins. Vertical margins disappear when parent is set to overflow:visible
Margin on child element moves parent element
Found an alternative at Child elements with margins within DIVs You can also add:
.parent { overflow: auto; }
or:
.parent { overflow: hidden; }
This prevents the margins to collapse. Border and padding do the same.
Hence, you can also use the following to prevent a top-margin collapse:
.parent {
padding-top: 1px;
margin-top: -1px;
}
2021 update: if you're willing to drop IE11 support you can also use the new CSS construct display: flow-root
. See MDN Web Docs for the whole details on block formatting contexts.
Update by popular request:
The whole point of collapsing margins is handling textual content. For example:
h1, h2, p, ul {
margin-top: 1em;
margin-bottom: 1em;
outline: 1px dashed blue;
}
div { outline: 1px solid red; }
<h1>Title!</h1>
<div class="text">
<h2>Title!</h2>
<p>Paragraph</p>
</div>
<div class="text">
<h2>Title!</h2>
<p>Paragraph</p>
<ul>
<li>list item</li>
</ul>
</div>
Can't prevent margins from collapsing
The problem is that the element you want the margin-bottom
on are floated. Therefore they don't extend their parent's height. so if you aply the margin on the parent, it will be "under" the floated elements.
Explanation for your case :
In your example li.product
has 2 children : a
and gk-columns
. .gk-columns
has only floated children so its height is 0 because floated elements don't extend parent's height. Therefore the height of li.product
is only extended by the a
tag which is 28px.
So if you aply margin-bottom:50px;
on li.product
it will push the content only of
28px + 50px = 78px
which is less than the height of the floated div.
You can solve this with several solutions :
solution 1
add the margin-bottom
on the floated elements like this for your example :
.gk-columns>div{
margin-bottom:50px;
}
Solution 2
if the height of the children elements is fixed set the height to the parent element so it covers the height of the floated children like this for you example :
.gk-columns{
height:159px;
}
How does the margin collapsing of parent and first/last child work?
I threw together this little demo to help demonstrate the way this works:
http://jsfiddle.net/9pq8bm0o/
As you can see, I've made three elements, all nested within each other. The 2 inner containers both have a top margin value of 20px
, and the outermost container has a top border (one of the things that is considered a margin separator).
So what does this mean?
Because there is no separation at the top of the two child elements, there is only 20px
of space in between the outermost container and BOTH of the two child elements... the inner-most child has had it's margin collapse. Conversely, that margin that is there exists within the outermost container simply because of that border.. if you remove the border, all three elements will share the same 20px
of margin which will be outside of all three containers.
So why is it like this?
The best way to think about margin collapsing is like this:
Asking for a margin on an element will ensure that it has that much margin at it's top, and nothing more (unless it's forced to have more).. So looking at my example, Does the middle .parent
element have 20px
of space above it? Yes, it does. Does the innermost child .child
have 20px
of space above it? Yes, it also does... so the margin rule is being applied correctly. It doesn't matter where that space lives, as long as it is there.
Imagine that there was a border around the .parent
element, but the margin was still displayed the way it is without, and then ask those same questions.. Does the .parent
element have the space? Yes, but does the .child
element? No, it no longer would, because there would not be 20px
of space in between it and the border that is now sitting above it... So, in reality, the space does not collapse, so that both of those questions can be answered as a "yes".
I hope that helps.. it's a little less of a direct answer to your question, and more of the theory behind how it works, so to put things a bit more plainly:
tl;dr
Margin, unlike padding, is meant to add space outside of elements. Because of this, margin will always collapse to the highest parent element whenever possible, to ensure that space is always "outside". Because it is outside of the element, it can count towards multiple different elements, as they all share that "outside" space.
CSS Right Margin Does Not Work Inside a Div With Overflow Scroll
TL;DR:
Margins are for moving an element in from the wrapper, not expanding the wrapper outwards.
The long explanation:
This behavior is consistent with specifying a width
in addition to a horizontal margin
anywhere in the document. To break it down, consider the following snippet, where I specificity a wrapper without an overflow
property, and the margin
does not expand the wrapper element.
body {
padding: 20px;
}
.outer {
width: 400px;
border: 1px solid black;
}
.inner {
width: 400px;
height: 40px;
margin: 0 20px;
background: grey;
}
<div class="outer">
<div class="inner">
</div>
</div>
Related Topics
Pseudo Element Not Aligning at Top Left Corner
Why the :Before and :After Pseudo-Elements Work Only in Firefox
Alternative to Page-Break-Inside:Avoid Because of Compatibility Issues
Scale Element in X and Y by the Same Amount of Pixels
Img with {Display: Table-Cell} -- Is It a Bug
CSS Images Not Showing in ASP.NET MVC
Flow Multi-Column Elements Left-Right Before Top-Down
How to Animate a Svg Figure Like a Progress Bar with CSS
How to Apply Different Styles to Different Letters in Word
How Does Internet Explorer 8 Support the CSS Outline Attribute
How to Code an Arrow Using CSS
Keeping A: Active Until Another Link Is Clicked
Is There a Specific Order for CSS Properties
Applying CSS on Drawn Canvas Elements
How to Add CSS to Selected Row in Treegrid Gxt 3
Material-Ui Makestyles Cannot Read Property 'Down' of Undefined