padding on parent turn margin of the child into height expandation - html

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;}

Related

overflow:hidden on div tag affects background color

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/

Giving a margin to a paragraph element doesn't actually apply to parent div

Given the following markup:
<div>
<p>Test test</p>
</div>
Setting the margin: 10px to the paragraph element should apply to both top and bottom, correct?
I have a simple example, and I don't quite know why it doesn't work.
http://jsbin.com/URumOFup/2/edit?html,css,output
This works as I expect it to if I give the div the rule of overflow: hidden. Can someone explain why this happens and if using overflow: hidden is the proper way to have the margins of p apply?
The general meaning of "margin" isn't to convey "move this over by 10px" but rather, "there must be 10px of empty space beside this element."
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:
Margins of the root element's box do not collapse.
If the top and bottom margins of an element with clearance are adjoining, its margins collapse with the adjoining margins of following siblings but that resulting margin does not collapse with the bottom margin of the parent block.
Since your outter DIV is not 'floated' .. top margin of inner element <p> will collapse to 0 for the first one, then collapse to a minimum spacing for other <p> tags.
Just 'float:left;width:100%' your div will solve your issue.
Margin-collapsing w3c reference

Why does adding a border change the height calculation?

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.

Always show greater margin

I have given one block a bottom margin of 25px and a top margin of 10px. The total margin should then be 35px but it is showing 25px. If I give 35px margin, then it shows the total of 35px. Why is it showing greater margin always?
Here are the code lines:
<p style="margin-bottom:25px; outline:1px dashed #000000;">aaaaaaaaaaaa</P>
<p style="margin-top:10px; outline:1px dashed #000000;">bbbbbbbbbbbbbbbb</p>
It's called "collapsing margins". This is normal, and is in accordance with the W3 standards. It says:
Margins of the root element's box do not collapse.
If the top and bottom margins of an element with clearance are
adjoining, its margins collapse with the adjoining margins of
following siblings but that resulting margin does not collapse with
the bottom margin of the parent block.
More info: http://www.w3.org/TR/CSS21/box.html#collapsing-margins
Therefore your two <p> tags:
<p style="margin-bottom:25px; outline:1px dashed #000000;">aaaaaaaaaaaa</p>
<p style="margin-top:10px; outline:1px dashed #000000;">bbbbbbbbbbbbbbbb</p>
would then collapse.
The specifications also mention cases where margins are not collapsed. For example, floated elements have non-collapsed margins:
Margins between a floated box and any other box do not collapse
And a fiddle demonstrating collapsed and non-collapsed margins:
Fiddle:http://jsfiddle.net/k8tFy/3/
(Note: you can even see the floated <p> tag is even interacting with the margin-bottom of the <h2> tag)
If short, that is how margins should work. Top and bottom margins may collapse and in that case final distance between two blocks will be equal to the width of largest margin.
For more details take a look at this part of CSS standart:
http://www.w3.org/TR/CSS2/box.html#collapsing-margins
When two or more margins collapse, the resulting margin width is the
maximum of the collapsing margins' widths.
Possible solutions:
You may simply put margin-bottom of top element to 35px, just like you described.
Another way is to make one of elements to be float:
<p style="margin-bottom:25px; outline:1px dashed #000000;clear:both;">aaaaaaaaaaaa</P>
<p style="margin-top:10px; outline:1px dashed #000000;clear:both;float:left;width:100%">bbbbbbbbbbbbbbbb</p>
Demo
Above solution based on next exception you may find on page linked above:
Margins between a floated box and any other box do not collapse (not
even between a float and its in-flow children).

Child elements with margins within DIVs

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>