Min-height and margin - css

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;

Related

CSS Odd Behavior: min-height and margin collapse

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.

Why does big negative margin-right make absolute element no wrap?

Update:
The position value will change the width.
The JSFiddle: http://jsfiddle.net/caicai/mbtb5m7p/2/
Why does the width of div .a2 equal to its parent's width, while the the text in the div .a1 won't wrap?
The JSFiddle: http://jsfiddle.net/caicai/mbtb5m7p/
.r {
position: relative;
width: 100px;
height: 22px;
background: blue;
}
.a1 {
position: absolute;
top: 30px;
margin-right: -9999px;
background: green;
}
.a2 {
position: absolute;
top: 60px;
background: orange;
}
<div class="r">
<div class="a1">
Why does this line no wrap.
</div>
<div class="a2">
Why does this line wrap.
</div>
</div>
The div.r has a width of 100px and is placed relative.
The children .a1 and .a2 are placed absolute. The related on their (relatively placed) parent.
Without a negative margin, the children will take a maximum width equal to its parents size.
But, by adding a negative margin, you allow the children to "float over" its parents borders.
It's not that the content of .a1 is no longer wrapping, it is that the content of .a1 has no need to wrap because the available interior space has been made wide enough for the string inside it by your negative margin.
So your div.a1 will essentially be the width of .r + the value of the negative margin, which is dragging out the right extremity and increasing the size of your div.
That's pretty much how the box model works, check it out here or here
The margin is something that depends on it's parent element(class/id) here class r for classes a1 and a2.
1) Now you have width:100px for parent class(Class .r) so all child classes(class a1 & a2) inherits same width.
2) There is no issue for class a2, that class is totally normal as no unique(different) property than parent class(.r), so behaves properly.
3) Now the case for class .a1, which behaves properly too till it finds margin-right:negativeValue;.
So first understanding margin, Margin is the space between class/element block and it's parent class/element block. For Example margin-left:5px; so that particular block starts after leaving 5px from left, respectively for rest three sides(top, bottom, right)
Now negative margins, when used what it does is it trespasses their parent blocks boundary. That is it gets beyond the boundaries of their parents.
So here you specified margin-right:-9999px; so it gets beyond the boundary of class .r, still it might be giving you a thought that -9999px is a huge value, should throw the div beyond the screen, but as of limited text it only shows the area contained with text.
Inserting more text in class a1 it will surely go beyond screen scope, but text should be more than enough.
Graphical Explanation Updated

How this float div is getting top margin when wrapper div has no border?

Please note that I am not asking about correcting the problem but instead I want to know how floated div is getting margin when wrapper div has 0px border set. But when wrapper div has 1px border set then floated div doesn't get margin but in both cases secondDiv gets top margin as intended.
Please note that I understand margin collapsing topic but what it has to do with setting border?
<div id="container">
<div id="firstDiv">FIRST Div inside CONTAINER</div>
<div id="secondDiv">SECOND Div inside CONTAINER</div>
</div>
body{
width: 780px;
margin: 00px auto;
}
#container {
border: 1px solid orange; /* but when its set to 0px then floated div gets margin too*/
}
#firstDiv{
float:left;
}
#secondDiv{
margin: 14px;
}
http://jsfiddle.net/dmpxw/
Now, if border of wrapper div is set to 0px then floated is pushed downward too. But I think shouldn't it stay there like in previous case?
http://jsfiddle.net/dmpxw/1/
This is an interesting one.
When the container has a border, the margin of the second inner div runs from the border - i.e. the margin applies from the border onwards. This is because the border is the last item that applies before the margin measurement.
When the container does not have a border, the margin of the second inner div runs from the last item, which is now the body. So the margin is now OUTSIDE of the container, so the container is now actually further down the page - the first inner div has no margin, and is right at the top of the container - it is the container itself that has moved in the second case.
If you add a background color to your example, you can see that when you have a border the margin is inside the container, and when you have no border the margin is outside the container. View the example on JSFiddle.

How to set a divs height to "100%" alternative?

I have to create a div that has a paper texture to it, with rounded corners. When the content inside grows, this div should grow along with it and not ruin the bg..
So to do this, I made the main div with the content, and made it repeat the center of the bg and set the height to auto. I made a div for the top and bottom parts of it with the textures and rounded corners. I used absolute positioning relative to the content div so when it grows, the bottom bg will be below the content div at all times.
Everything looks good BUT, the top and bottom divs are covering the content div. I can fix this by leaving a large gap at the top and bottom of the content div but it looks strange having such a large gap.. and its improper.
Any ideas around this?
Try adding a margin to the top and bottom of the content div (ie. margin: 20px 0 30px 0; where 20 is the height of your top div and 30 is the height of your bottom div). Also, can't you just put the three divs in a container and position them relatively, one stacked on another?
Example:
<div id="container">
<div id="top"></div>
<div id="content"></div>
<div id="bottom"></div>
</div>
It´s hard to say without looking at your code, but I think your problem can be easily solved by adding a top and bottom padding to your main div, the size of the top and bottom parts.
Edit: An alternative would be to put your content in another div in the main div and abandon absolute positioning. Just put all three divs one after the other and use negative margins to pull the content up over the top div and do something similar for the bottom border.
Use z-index: http://www.jsfiddle.net/xPEY6/
(Per the CSS spec you don't actually need the .text div, you could set .top and .bottom to z-index: -1 and .container to z-index: 0, but I wouldn't rely on all browsers implementing that detail correctly.)
You can do this with positioning:
div.paperTexture {
position: absolute;
top: 0px;
bottom: 0px;
}
Also works well if you need the div to take up 100% of the viewport minus Xpx. Just set the top or bottom to Xpx.

Main column appears where sidebar column ends

I'm braindead on this and I know it's simple.
There's a header div, appears fine. There's a left-sidebar div, appears fine with top snuggled up to header div.
Then there's a main content div. There is an image and h1 which appear like you would expect up against the header div, but then a large gap appears until the navigation (in a nested div). Navigation is correctly in the main content div, but top of this div always aligns with bottom of sidebar content.
I've tried mixtures of clear:left and both and floating and whatnot. If inside the html I move the sidebar div below the main content div then the main content has no gap but the sidebar has a big top gap and appears flush to the bottom of where the main content nav ends.
What am I missing here, thanks in advance!
Are you setting any widths (or padding, margin, border) which might make your problematic div too wide to fit?
Remember that if you are doing something like :
width: 100%;
border: 1px solid;
Then your element will take up 100% width + 2 pixels.
It sounds like you have your sidebar occuring first in the source order.
If you have the two divs (sidebar, main) floated in different directions, then look at the width avaiable they are sharing. Reduce the width of one div (you should have width set on your floats) until their combine width, including padding, margin, borders fits in available space. (I will only use width in my example for brevity).
When this effect happens, in my experience, the one occurring later in the source order is the one that gets prevent from sliding up into it's spot by too much width.
<div id="container">
<div id="header">head</div>
<div id="sidebar">side</div>
<div id="mainContent">main</div>
</div>
Width of #sidebar & #mainContent too wide (#mainContent gets bumped down):
#container{
**width:950px;**
margin:0 auto;
background:blue;
}
#mainContent{
float:right;
**width:651px;**
background:red;
}
#sidebar{
float:left;
**width:301px;**
background:green;
}
Width of #sidebar & #mainContent fit inside container:
#container{
**width:950px;**
margin:0 auto;
background:blue;
}
#mainContent{
float:right;
**width:650px;**
background:red;
}
#sidebar{
float:left;
**width:300px;**
background:green;
}
btw...if you floated the two elements in the same direction, but their combined width is too wide, the last one in the source order would fit underneath the above floated element.
Does your h1 or img have a top margin? It will stick out of the top of the mainContent div and push it down.

Resources