I have got two divcontainers one with a border and one without the border.
Inside both containers I got a p paragraph with a margin of 1em.
Obviously both container should have the same height.
Surprisingly that is not the case for Firefox, Chrome, Safari, and IE.
Fiddle demo
CSS:
p { display: block; margin: 1em }
HTML:
<div>
<p></p>
</div>
<div style="border: 1px solid black">
<p></p>
</div>
What's the reason for this behavior?
The first p element's margins are collapsing with its parent div. This means the margins on the p element are combining with the zero margins on your div, causing them to cross the boundaries of the div. As a result, the height of the div is reported to be the same as its p child.
In the second group of elements, margin collapse is prevented when you add a border. This causes the parent div to completely contain both the p element as well as its margins. So the height of the div becomes the sum of the p element's height and its vertical margins.
Remember that p elements have default vertical margins, and that most block elements have no fixed height (i.e. are height: auto by default), so they'll only be as tall as is necessary to fit their contents. When a child's margins are collapsing with its parent's margins, those margins are not included when calculating the parent's height.
Related
The definition of overflow:hidden states that :
the overflowing content is completely hidden, not accessible to the user.
from: http://quirksmode.org/css/css2/overflow.html
But i am curious about this behavior from my js fiddle:
https://jsfiddle.net/gd62qmr3/2/
One thing i noticed is that, it gave color to the margins after setting the overflow to hidden?
<div style="background-color:green;overflow:hidden;">
<p>test</p>
</div>
I wanna know why did such behavior occur? the exact block element will have the green background color if there is no overflow but putting overflow will give background color to its margins.
That's because overflow: hidden affects margin collapse.
p elements have some vertical margin by default. According to the spec, it collapses with the margin of the parent div:
In CSS, the adjoining margins of two or more boxes (which might or
might not be siblings) can combine to form a single margin. Margins
that combine this way are said to collapse, and the resulting combined
margin is called a collapsed margin.
Adjoining vertical margins collapse, except [... not
relevant]
[... The] top margin of a box and top margin of its first in-flow
child [are adjoining]
However, overflow: hidden prevents that:
Margins of elements that establish new block formatting contexts (such
as floats and elements with overflow other than visible) do not
collapse with their in-flow children.
Your color is set to the parent of your paragraph. You have nothing stopping the height of your parent div to expand as far as it wants, so the paragraph margins are making the parent height larger.
If you were to give a set height to your parent (18px or so) then it will hide the margins (and text technically)
div {
height:18px;
}
https://jsfiddle.net/gd62qmr3/3/
If you were to set the color to your paragraph, then you will not see the background color in the margins
div {
overflow:hidden;
}
div p {
background-color:green;
margin:20px 0;
}
https://jsfiddle.net/gd62qmr3/4/
There is a block:
<div class="block">
<p>this is a paragraph this is a paragraph</p>
</div>
And its style:
.block{background:gray; width:300px}
p{margin-top:50px}
This is the result:
Well, but when I add padding-top to the .block, the result differs:
.block{background: gray; width:300px; padding-top:1px}
p{margin-top:50px;}
The result:
It looks that by adding padding to the parent, the margin of the child (p) caused expanding.
You could checkout the fiddles: http://jsfiddle.net/YFU2f/2/ and http://jsfiddle.net/YFU2f/3/
By default, adjacent margins collapse, when you introduce a padding between them they aren't anymore adjacent, so they become separate.
In your example, the top margin you defined on the p element collapses with the top margin of the body element (which is usually 8px by default), so at the end, the distance between the top of the canvas and the top of the content box of p is 50px. If you introduce the padding, it becomes 8px+1px+50px=59px. You can also notice the collapse of the margin by looking at the background of the div: when the margin collapses, it is as if the 50px margin was only declared for the body.
You can find all the details in the specifications: http://www.w3.org/TR/CSS21/box.html#collapsing-margins
you need to use display p as block
p{margin-top:50px;display:inline-block;}
This might be due to margin collapsing and I know about margin collapsing, at least how it affects adjacent elements, but I don't understand how it works on nested elements when negative margins are involved.
For example, in this markup and accompanying CSS:
Markup
<div class="parent">
<div class="child">
Child 1
</div>
</div>
<div class="parent">
<div class="child negative">
Child 1
</div>
</div>
CSS
body {
background: white;
padding: 45px;
}
.parent {
border: 1px solid black;
margin-bottom: 10px;
}
.negative {
margin-bottom: -1px;
}
Live example here.
When I inspect the height of the second .parent div, I notice it is 1 pixel less than the first one. This has happened because of the negative margin on the .negative element inside it. I had a quick look at W3C and couldn't find an explanation for this behavior.
Could someone please explain what's happening here and also provide me with a link to the W3C spec section about it?
This might be due to margin collapsing and I know about margin collapsing, at least how it affects adjacent elements, but I don't understand how it works on nested elements when negative margins are involved.
Section 8.3.1 has all the details. It also covers the behavior of adjoining margins between nested boxes, as well as negative margins.
However, what you're seeing here is not the effect of margin collapse because you have negated it with a border: 1px solid black declaration in your .parent rule. That means having a border there prevents your .parent margin from collapsing with your .child.negative margin altogether.
Rather, this is simply how negative margins work. This is covered in various sections of the visual formatting model, but it's most succinctly and directly addressed in the beginning of Section 11, which summarizes it thus:
Generally, the content of a block box is confined to the content edges of the box. In certain cases, a box may overflow, meaning its content lies partly or entirely outside of the box, e.g.:
...
A descendant box has negative margins, causing it to be positioned partly outside the box.
So what's happening here, instead, is:
The absolute value of the .child.negative element's negative margin is subtracted from the .parent element's actual height (by 1px).
As a result, the .child.negative element itself overflows .parent (because its own height is not changed and the default overflow for any div is visible).
Since margin collapse does not take effect here, the margin-bottom: 10px in your .parent is unaffected. Note that while any subsequent elements in normal flow will be shifted up by 1px, this is mainly due to the negative margin of your .child.negative element; in other words, a side effect of step 1.
And that's all there is to it.
when you are using .negative { margin-bottom: -1px; } then it will moved at the top. see this example.
please refer the following link you understand easily.
http://coding.smashingmagazine.com/2009/07/27/the-definitive-guide-to-using-negative-margins/
body {
background: white;
padding: 45px;
}
.parent {
border: 1px solid black;
margin-bottom: 10px;
min-height: 30px;
}
.negative {
margin-bottom: 20px;
}
conclusion:
For e.g. In your case i have to added min-height:30px to parent class so that it remains fix. if moved only if you add positive margins to negative class. It just because you can see results in above figure that tells all what you need is.
see the cssdesk link click here cssdesk
Hope, it will helps you. Cheers. !!
Margins of first and last elements will apply to outer element when the outer element doesn't have border, padding and content, instead of it self.
In your case, parent node has border, so margin collapsing won't apply in this case. As you have margin-bottom = -1px for the child node inside, when calculate the outer height of the child node will be the height of its content + padding + border-width + margin. So it will be 1px less when measuring from outside. That's why the height of parent node will be 1px less than the upper example. To see it more clearly, you may apply a background to the child node, say yellow, you will find that the child node will overlap the border of the parent node.
But if you remove the border of the parent node, it will be a total different situation.
For instance to explain margin collapsing, say you have
<div style="background-color:black">
<div style="height:10px; background-color:white; margin-top: 10px"></div>
</div>
You will not see a black box of 10px height, as the outer node will be considered to have a 10px margin on top, and the inner one's margin is ignored. And for negative situation, the outer margin will decrease.
Quote from spec:
When two or more margins collapse, the resulting margin width is the maximum of the collapsing margins' widths. In the case of negative margins, the maximum of the absolute values of the negative adjoining margins is deducted from the maximum of the positive adjoining margins. If there are no positive margins, the maximum of the absolute values of the adjoining margins is deducted from zero.
For more info:
https://developer.mozilla.org/en-US/docs/CSS/margin_collapsing
The problem:
An element with display: inline-block; will have a different margin than an element with display: block; even if the margin is set to for instance margin-top: 30px; for both!
The margin-top will apply for the element with inline-block, but not precisely the same as for an element with block. There will be some pixels in difference. Why?
I think what you're referring to is the fact that margins of inline-block elements do not collapse, but on block elements they do collapse. The Box model page goes over this really well.
So what is a collapsing margin? Say you have an element with 10px margin on the bottom followed by an element with 5px margin on the top. The margin between the two will not be 15, but will collapse down to the largest of the two (10px).
Inline-blocks have by default a padding between them, (the size of a space, so 1em in width) if the element tags are not placed next to eachother without space:
<element></element><element></element>
Will be okay, but the following will not:
<element></element>
<element></element>
Blocks do not have this issue, that's why it seems different. It adds the default to the padding with the inline.
To overcome this, you can set the parent font-size to 0, or subtract the extra padding width from your desired width.
I need two consecutive div elements (with backgrounds) to be touching seamlessly, one below the other. However, this layout breaks when I put a child p element into the bottom div. The margins of the p element force a blank gap between both div elements. This is strange behavior, as I am expecting the margin of the p to stay within the content and background area of the div. It renders the same way on Firefox, Chrome and IE 8.
<div style="background: #ccccff">Top Div</div>
<div style="background: #ffcccc"><p>Bottom Div</p></div>
Here's what it looks like.
I could fix this by changing the margins to paddings for the p element, but then I would also have to do this with header elements, list elements, and any other element I want to use at the start of a div. That is not desirable.
Could someone enlighten me: what caveat of the box model am I missing? Is there an easy way to fix this, preferably by modifying the style of the div?
Add overflow: hidden or overflow: auto to the div
That is the expected behavior*. There are a few ways to get around it. If you float the divs, they will contain the margins of child elements and prevent margin collapsing. Another approach is to add a border or padding to the divs.
* The margins of the div and the p "combine to form a single margin", even though they are nested, because they have adjoining margins with no padding or border between them.
Solution 1
Add overflow: hidden/auto to the containing div to prevent the margin collapsing.
Solution 2
Add positive padding to the containing div and equal negative margin to the inner element
New Solution
Add padding of 0.01px to the containing div, this will prevent the margin collapsing but won't need any negative margin on the inner element.
Setting a positive padding, and a corresponding negative margin on the div element seems to fix the issue, though I know not why.
<div style="background: #ccccff">Top Div</div>
<div style="background: #ffcccc; padding: 1px; margin: -1px"><p>Bottom Div</p></div>