CSS Odd Behavior: min-height and margin collapse - css

Consider the following code:
.container {
min-height: 100px;
background-color: lightgreen;
}
p {
margin-bottom: 50px;
}
<div class="container">
<p>Welcome</p>
</div>
<div class="after">
Main content.
</div>
http://jsfiddle.net/Lp4tp/31/
Question:
MDN's margin collapse page states that if there is min-height set on a parent element, this will prevent its bottom margin from adjoining with its last child's bottom margin - which will prevent margin collapsing. To me, this makes sense.
Parent and first/last child:
If there is no border, padding, inline part, block_formatting_context created or clearance to separate the margin-top of a block from the margin-top of its first child block, or no border, padding, inline content, height, min-height, or max-height to separate the margin-bottom of a block from the margin-bottom of its last child, then those margins collapse. The collapsed margin ends up outside the parent.
In this example, however, DevTools shows the bottom margin of the p tag where it would be expected - directly beneath the p element - but then there is 50px of blank space below the container, which doesn't make sense. The margin of the p tag seems to still be collapsing somehow, ending up outside the parent and affecting the position of the next element, even though the margin of the p and .container are not adjoining, and DevTools shows the p tag's margin nowhere near the bottom of .container.
Anyone have any explanations for why the margin is still sort of collapsing and leaving the blank space below .container? Also, is the MDN page wrong in saying that min-height will prevent margin collapse?
Thanks

apply display: flow-root; on the parent container. This should fix it.

Related

Strange behavior on computed height and childrens margin

I want to know the real height of an element no matters what it have inside. That's easy. The problem began when I put away the borders of the element and notice an strange behavior, see it here:
http://jsfiddle.net/LypZR/
First div: 122px: OK (children height 100px, children margins 20px, border 2px)
.bordered {
border: 1px solid #000;
}
Second div: 120px: OK (children height 100px, children margins 20px)
.display-inline-block {
display: inline-block;
}
Thirth div: 100px: What? where are the margins?
I solved it using display: inline-block that works just fine for me (in this particular case). But I really want to know what is exactly happening.
I think you're getting surprised by margin collapsing.
The two cases that margins collapse are between adjacent sibling elements and between parent and child elements.
In your case, it's the parent/child collapse that's causing you grief: If you have nothing interesting between the top margin of your parent and the (top margin of its first child|bottom margin of its last child), the parent margin collapses. The transparent border hack is commonly-used in these cases.
You probably noted that it didn't change the actual layout values--the p tag's margin kept the visible elements from collapsing into each other. But I admit it's counterintuitive.
That's called the margin collapsing.
When the child element is given margin and parent element don't have any content in it, this happens.
add this class and its done.
.no-bordered{
overflow:auto;
}
Fiddle : http://jsfiddle.net/LypZR/3/
you can see real height without any collapse if you use the right css selector for all the elements *, so:
* {
height: 100px;
margin: 10px;
}
Like you did it's like a quirk behave for me because I don't know .element selector, and if you look inside the consolle could you see that no margin is applied in the styles tab, but only a computed height is calculated, perhaps for some strange behavior it isn't suppouse to work right. till I know only height width and padding are considerate for real element dimensions.
margins should not be considerate for real element dimensions, this is only an IE issue who do such calc adding margin to real element dimensions. jsfiddle

Min-height and margin

Consider the following HTML:
.top {
min-height: 150px;
}
p {
margin: 50px;
}
div {
background-color: #eee;
}
<div class="top">
<p>Welcome</p>
</div>
<div class="content">Main content</div>
You can see it in action here:
http://jsfiddle.net/Lp4tp/1
Question
In Chrome(for Ubuntu), it appears that the margin defined on the p tag causes spacing between the top div and it's surrounding elements, instead of expanding the top div and producing the equivalent of adding 50 pixels padding on the top div.
Is this correct behavior? And if so, how can I ensure that child elements inside the top div cannot create undesired space between the top div and the content div.
Note
If I use a fixed height instead of a minimum height, the spacing between the top and the content div vanishes, but the top still produces 50 pixels of white space above itself.
Your margins collapse. Fix with overflow:auto on the div:
div {
background-color: #eee;
overflow:auto;
}
jsFiddle example
Top and bottom margins of blocks are sometimes combined (collapsed)
into a single margin whose size is the largest of the margins combined
into it, a behavior known as margin collapsing.
You could also add a border to the div for the same result.
add to p
display:inline-block;

Can't prevent margins from collapsing

I had to to let a hover div menu get out of its container, so I declared that container with overflow: visible and it works, but now that container has lost its margin-bottom with the rest of the following in the list.
I've read this question and this one, as well as read a few other articles, and have tried putting paddings and the html code referenced on different elements, but I can't get what is going wrong in my specific case.
The url is http://melopienso.com/testingtwo/shop/ and each "ul.products li" should be having the bottom margin.
Any ideas? Thank you very much for your help!
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;
}

CSS 2.1 spec: 8.3.1 Collapsing margins: cannot properly interpret special case: clarification sought

Section 8.3.1 of the CSS 2.1 spec on collapsing margins states:
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.
Here is my, surely erratic, attempt at making something out of this statement:
The statement considers an element X for which:
X has clearance, therefore either of the "clear: left;", "clear: right;"
or "clear: both;" properties have been applied to it.
Since the top AND bottom margins of X are adjoining,
in the case of a normal flow we are considering the scenario where:
X has one parent above and one sibling below, or
X has one sibling above and one sibling below, or
X has one sibling above and one parent below
Then the spec says, "its margins collapse with the adjoining margins
of following siblings", but there can be at most one following sibling,
as pointed out above, so this essentially must mean that if there is a
sibling following then the margin collapses.
"but that resulting margin does not collapse with the bottom margin
of the parent block." - I don't understand this: if the bottom margin
is adjacent to a sibling's top margin then it cannot be adjacent to
the parent block's bottom margin unless the sibling's height is zero.
I'm utterly confused. Can someone please explain this statement in a better way, perhaps with a few illustrative examples?
First, a couple of clarifications:
An element with clearance is one which has clear set to something other than none and is actually clearing a float.
An element whose top and bottom margin are adjoining means adjoining with each other, not with siblings. We're talking about a 0 height element without border or padding, so the top margin and bottom margin of the element are touching each other. When this happens, they collapse with together, a situation known as collapsing through.
Now, let's look at an example:
body {
border:solid;
}
#container {
margin: 20px;
background: blue;
}
#floated {
float: left;
width: 20px;
height: 20px;
background: red;
}
#cleared {
clear: left;
margin-top: 10px;
margin-bottom: 20px;
}
#following {
margin-top: 30px;
}
<body>
<div id=container>
<div id=floated></div>
<div id=cleared></div>
<div id=following></div>
<div>
</body>
Play with it here: http://jsbin.com/wuvilu/1/edit?html,css,output
Since there is a border on the body, you can see the 20px margin around the blue #container. The red #floated is also an obvious 20px by 20px.
Then, since it is 0 height with no padding and no border, the top and bottom margin of the #cleared collapse with each other. They are also adjoining with the top margin of the #following. The size of this collapsed margin is 30px, the largest of the three.
Since the #following is 0 height and has no padding and no border, our 30px margin is adjoining with the bottom margin of the #container, and would collapse with it. Except now the rule you have quoted kicks in, and it doesn't.
Since it won't collapse with the bottom margin of the container, it has to be placed somewhere within it. Where? It starts from 10px above the bottom edge of #floater, and extends 20px below. Why? The top margin of #cleared is the top-most margin that participates in this collapse margin, so we start where it would start. Since it is 10px, our collapsed margin starts 10px above the bottom edge of #floater, the element immediately before it.
Yes, this is insane, and most scenarios that involve collapsing through are insane. Collapsing through was a terrible idea, and it should never have made it into CSS, but it did before people knew better, and now we have to deal with it, and all the crazy consequences.

What is the difference between `margin` and `padding` in CSS?

What is the difference between margin and padding in CSS?
In what kind of situations:
both work.
only margin is appropriate.
only padding is appropriate.
TL;DR: By default I use margin everywhere, except when I have a border or background and want to increase the space inside that visible box.
To me, the biggest difference between padding and margin is that vertical margins auto-collapse, and padding doesn't.
Consider two elements one above the other each with padding of 1em. This padding is considered to be part of the element and is always preserved.
So you will end up with the content of the first element, followed by the padding of the first element, followed by the padding of the second, followed by the content of the second element.
Thus the content of the two elements will end up being 2em apart.
Now replace that padding with 1em margin. Margins are considered to be outside of the element, and margins of adjacent items will overlap.
So in this example, you will end up with the content of the first element followed by 1em of combined margin followed by the content of the second element. So the content of the two elements is only 1em apart.
This can be really useful when you know that you want to say 1em of spacing around an element, regardless of what element it is next to.
The other two big differences are that padding is included in the click region and background color/image, but not the margin.
div.box > div { height: 50px; width: 50px; border: 1px solid black; text-align: center; }
div.padding > div { padding-top: 20px; }
div.margin > div { margin-top: 20px; }
<h3>Default</h3>
<div class="box">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
<h3>padding-top: 20px</h3>
<div class="box padding">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
<h3>margin-top: 20px; </h3>
<div class="box margin">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
Margin is on the outside of block elements while padding is on the inside.
Use margin to separate the block from things outside it
Use padding to move the contents away from the edges of the block.
The best I've seen explaining this with examples, diagrams, and even a 'try it yourself' view is here.
The diagram below I think gives an instant visual understanding of the difference.
One thing to keep in mind is standards compliant browsers (IE quirks is an exception) render only the content portion to the given width, so keep track of this in layout calculations. Also note that border box is seeing somewhat of a comeback with Bootstrap 3 supporting it.
There are more technical explanations for your question, but if you want a way to think about margin and padding, this analogy might help.
Imagine block elements as picture frames hanging on a wall:
The photo is the content.
The matting is the padding.
The frame moulding is the border.
The wall is the viewport.
The space between two frames is the margin.
With this in mind, a good rule of thumb is to use margin when you want to space an element in relationship to other elements on the wall, and padding when you're adjusting the appearance of the element itself. Margin won't change the size of the element, but padding will make the element bigger1.
1 You can alter this behavior with the box-sizing attribute.
MARGIN vs PADDING :
Margin is used in an element to create distance between that element and other elements of page. Where padding is used to create distance between content and border of an element.
Margin is not part of an element where padding is part of element.
Please refer below image extracted from Margin Vs Padding - CSS Properties
From https://www.w3schools.com/css/css_boxmodel.asp
Explanation of the different parts:
Content - The content of the box, where text and images appear
Padding - Clears an area around the content. The padding is transparent
Border - A border that goes around the padding and content
Margin - Clears an area outside the border. The margin is transparent
Live example (play around by changing the values):
https://www.w3schools.com/css/tryit.asp?filename=trycss_boxmodel
It's good to know the differences between margin and padding. Here are some differences:
Margin is outer space of an element, while padding is inner space of an element.
Margin is the space outside the border of an element, while padding is the space inside the border of it.
Margin accepts the value of auto: margin: auto, but you can't set padding to auto.
Tip: You can use the trick to make elements centered inside their parents (even vertically). See my other answer for example.
Margin can be set to any number, but padding must be non-negative.
When you style an element, padding will also be affected (e.g. background color), but not margin.
Here is some HTML that demonstrates how padding and margin affect clickability, and background filling. An object receives clicks to its padding, but clicks on an objects margin'd area go to its parent.
$(".outer").click(function(e) {
console.log("outer");
e.stopPropagation();
});
$(".inner").click(function(e) {
console.log("inner");
e.stopPropagation();
});
.outer {
padding: 10px;
background: red;
}
.inner {
margin: 10px;
padding: 10px;
background: blue;
border: solid white 1px;
}
<script src="http://code.jquery.com/jquery-latest.js"></script>
<div class="outer">
<div class="inner" style="position:relative; height:0px; width:0px">
</div>
</div>
The thing about margins is that you don't need to worry about the element's width.
Like when you give something {padding: 10px;}, you'll have to reduce the width of the element by 20px to keep the 'fit' and not disturb other elements around it.
So I generally start off by using paddings to get everything 'packed' and then use margins for minor tweaks.
Another thing to be aware of is that paddings are more consistent on different browsers and IE doesn't treat negative margins very well.
The margin clears an area around an element (outside the border), but the padding clears an area around the content (inside the border) of an element.
it means that your element does not know about its outside margins, so if you are developing dynamic web controls, I recommend that to use padding vs margin if you can.
note that some times you have to use margin.
One thing to note is when auto collapsing margins annoy you (and you are not using background colours on your elements), something it's just easier to use padding.
Advanced Margin versus Padding Explained
It is inappropriate to use padding to space content in an element; you must utilize margin on the child element instead. Older browsers such as Internet Explorer misinterpreted the box model except when it came to using margin which works perfectly in Internet Explorer 4.
There are two exceptions when using padding is appropriate to use:
It is applied to an inline element which can not contain any child elements such as an input element.
You are compensating for a highly miscellaneous browser bug which a vendor *cough* Mozilla *cough* refuses to fix and are certain (to the degree that you hold regular exchanges with W3C and WHATWG editors) that you must have a working solution and this solution will not effect the styling of anything other then the bug you are compensating for.
When you have a 100% width element with padding: 50px; you effectively get width: calc(100% + 100px);. Since margin is not added to the width it will not cause unexpected layout problems when you use margin on child elements instead of padding directly on the element.
So if you're not doing one of those two things do not add padding to the element but to it's direct child/children element(s) to ensure you're going to get the expected behavior in all browsers.
First let's look at what are the differences and what each responsibility is:
1) Margin
The CSS margin properties are used to generate space around elements.
The margin properties set the size of the white space outside the
border. With CSS, you have full control over the margins. There are
CSS properties for setting the margin for each side of an element
(top, right, bottom, and left).
2) Padding
The CSS padding properties are used to generate space around content.
The padding clears an area around the content (inside the border) of
an element. With CSS, you have full control over the padding. There
are CSS properties for setting the padding for each side of an element
(top, right, bottom, and left).
So simply Margins are space around elements, while Padding are space around content which are part of the element.
This image from codemancers shows how margin and borders get togther and how border box and content-box make it different.
Also they define each section as below:
Content - this defines the content area of the box where the actual content like text, images or maybe other elements reside.
Padding - this clears the main content from its containing box.
Border - this surrounds both content and padding.
Margin - this area defines a transparent space that separates it from other elements.
I always use this principle:
This is the box model from the inspect element feature in Firefox. It works like an onion:
Your content is in the middle.
Padding is space between your content and edge of the tag it is
inside.
The border and its specifications
The margin is the space around the tag.
So bigger margins will make more space around the box that contains your content.
Larger padding will increase the space between your content and the box of which it is inside.
Neither of them will increase or decrease the size of the box if it is set to a specific value.
Margin
Margin is usually used to create a space between the element itself and its surround.
for example I use it when I'm building a navbar to make it sticks to the edges of the screen and for no white gap.
Padding
I usually use when I've an element inside a border, <div> or something similar, and I want to decrease its size but at the time I want to keep the distance or the margin between the other elements around it.
So briefly, it's situational; it depends on what you are trying to do.
Margin is outside the box and padding is inside the box

Resources