CSS min-height adds to child element's bottom margin - html

I've been having a very weird CSS issue. Some of my pages have displayed an unexplained "space" between element. Inspecting the code shows that this space does not belong to any element.
I've narrowed it down, and I think I know why this issue is happening. But I wanted to know, under the hood, why it's happening.
The issue, I think, is that min-height: 50px in the #outer selector adds the bottom margin of #inner below #outer, which results in an the unexplained space mentioned above. If it were to be replaced with height: 50px the space would disappear.
This happens on Chrome but not FireFox.
My theory is that Chrome's CSS lays out the elements first then checks if min-height requirement is met. If not, then it extends the height of the div, pushing the "unexplained space" along with it. It essential copied, or inherited, the bottom margin of the child element. I think this only happens to the bottom margin though.
I've tried two tests of this theory, adding padding: 1px; and adding overflow: hidden; they both cause the height of the div to include it's child and thus gets rid of the issue. Although, I think in the case of overflow: hidden it's more cutting off the overflown content.
But I'm no CSS expert, all this is just speculation on my part, which is why I wanted to pose this as a question :)
Here's the code
#outer {
background-color: blue;
min-height: 100px;
}
#inner {
background-color: red;
height: 50px;
margin-bottom: 50px;
}
#bottom {
background-color: green;
height: 50px;
}
<div id="outer">
<div id="inner">
</div>
</div>
<div id="bottom">
</div>

This occurs due to margin collapsing - specifically the margin-bottom of inner collapses to become the margin-bottom of the outer element.
Solution:
Give a border to the outer element to prevent the margin collapsing - see demo below:
#outer {
background-color: blue;
min-height: 100px;
border: 1px solid blue;
}
#inner {
background-color: red;
height: 50px;
margin-bottom: 50px;
}
#bottom {
background-color: green;
height: 50px;
}
<div id="outer">
<div id="inner">
</div>
</div>
<div id="bottom">
</div>

Related

In CSS, the "margin" of element has no effect for the "height" of its parent?

Following is the snippet (demo on JSFiddle)
#inner {
background-color: yellow;
margin-left: 50px;
margin-bottom: 50px;
}
#outer {
background-color: red;
}
<div id="outer">
<div id="inner">
test
</div>
</div>
As can be seen in the demo, the #inner element has a margin-bottom.
I expected the height of #outer will be large enough to include the outline of #inner margin. And the output will have a red bar below the yellow bar.
However, I found the #outer's height is not changed at all though I added the rule margin-bottom: 50px for #inner.
Does anyone have ideas about this? And is there a way to ensure the content area of parent is large enough to hold the outline of its child's margin?
Also, apart from giving a hack solution, it would be great if the answer can include some explanation or links to related document/article. And why is the margin rule designed like this.
Thanks!
What you are seeing is the collapsing margins problem.
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.
Out of the three cases, yours is the case of collapsing margins between parent and child elements.
If there is no border, padding, inline content, height, min-height, or
max-height to separate the margin-bottom of a block with the
margin-bottom of its last child, then those margins collapse. The
collapsed margin ends up outside the parent.
If you add another element just after your parent div you will see that the margin ends up outside of it. The snippet below, shows you the collapsed margin:
#inner { background-color: yellow; margin-left: 50px; margin-bottom: 50px; }
#outer { background-color: red; }
<div id="outer">
<div id="inner">
test
</div>
</div>
<p>You can see the collapsed margin above this text outside of the parent div.</p>
Here is the reference from the specs: http://www.w3.org/TR/CSS21/box.html#collapsing-margins
How to fix this?
The solution is given in the quoted ref text itself above. Just apply any one of these to your parent div - border, padding, height, min-height, or max-height.
Easiest way to fix this would be to add a border to your outer div:
#outer { background-color: red; border: 1px solid gray; }
Better still, apply padding to the parent div instead of the margin on inner one.
#outer { background-color: red; padding-bottom: 50px; }
Examples:
Fiddle (with border): http://jsfiddle.net/abhitalks/rrtfhyky/1/
Fiddle (with padding): http://jsfiddle.net/abhitalks/rrtfhyky/2/
Snippet (with padding):
#inner { background-color: yellow; margin-left: 50px; }
#outer { background-color: red; padding-bottom: 50px; }
<div id="outer">
<div id="inner">
test
</div>
</div>
<p>Some text that follows.</p>
I had the same problem, just add overflow: auto to #outher div and it will fix the parents height
#inner {
background-color: yellow;
margin-left: 50px;
margin-bottom: 50px;
}
#outer {
overflow: auto; /* ADDED */
background-color: red;
}
<div id="outer">
<div id="inner">
test
</div>
</div>
Add This CSS
#inner {
background-color: yellow;
margin-left: 50px;
margin-bottom: 50px;
display: inline-block;
}
give a border to outer div :
#inner {
background-color: yellow;
margin-left: 80px;
margin-bottom: 50px;
}
#outer {
background-color: red;
border:1px solid white;
}
<div id="outer">
<div id="inner">
test
</div>
</div>
I know this common "bug", what I would do if I were you is changing the margin into padding and put it to the outer div:
My solution:
#inner {
background-color: yellow;
}
#outer {
background-color: red;
padding-left: 50px;
padding-bottom: 50px;
}
Also there are 3 other possible fixes:
By #Jenti Dabhi is the add the display:inline-block to the #inner div:
#inner {
background-color: yellow;
margin-left: 50px;
margin-bottom: 50px;
display: inline-block;
}
By #Chris is to add overflow: auto to the #outer div:
#outer {
overflow: auto;
background-color: red;
}
By #Abhitalks is to add a border to your #outer div:
#outer {
background-color: red; border: 1px solid gray;
}
This is a Typography concept,
generally, vertical margins of adjacent elements collapse!
Have a look at this article

CSS Box expanding bug / feature

Found an interesting browser behaviour. Given the following code:
div {
padding: 5px 10px;
color: #FFF;
}
.a {
float: left;
/* fix either set width or remove float */
background: goldenrod;
}
.b {
position: relative;
overflow: hidden;
background: #392;
}
.b div {
width: 20000em;
background: #942;
}
and
<DIV class="a">
<DIV class="b">
<DIV>Content</DIV>
</DIV>
</DIV>
I would expect the overflow: hidden to hide/crop the div to the viewport, but the parent float is honoured instead and the page is WIIIIIIIDE.
Anyone know if this a feature or a browser bug?
I know that you should add a width to a float ... but this felt weird to me. To stop the behaviour, either remove the float on .a or add max-width: 100% or similar.
[Note: found in html spaghetti mixing ektron, jcarousel with bootstrap, this is simplest test case to reproduce issue.]
Demo at http://codepen.io/elliz/pen/wteya

Float-left disabled padding

Two divs are side by side, one is floating left with a width of 25%, the other just has a width of 75%. But when padding is applied on the right hand div, the padding doesn't work properly.
Here is a JSfiddle example:
http://jsfiddle.net/88upt/
<div id="top">
</div>
<div id="middle">
</div>
<div id="bottom">
</div>
CSS
#top {
float: left;
background-color: green;
width: 25%;
height: 100%;
}
#middle {
background-color: blue;
padding: 30px;
min-height: 30%;
}
#bottom {
background-color: red;
min-height: 70%;
}
Can someone explain to me why this is happening?
Thanks
Floating something is kind of like making it's position absolute. It will hover on top of it's neighboring containers. Add a margin-left equal to the width of the floated element to make the container the correct width.
http://jsfiddle.net/88upt/4/
#middle {
background-color: blue;
padding: 30px;
min-height: 30%;
margin-left:25%
}
EDIT Elaborating a bit more.
The floated element pushes the content of the sibling elements over. It will not push the left side of the content's element over. The padding is there it's just hidden by the floating element.
Add overflow = "auto" in the #middle.
#middle {
background-color: blue;
padding: 30px;
min-height: 30%;
overflow: auto;
}
In this way, you don't need to know the width of floating element.
Width doesn't factor in padding.
Source: http://www.w3schools.com/css/css_boxmodel.asp
The width only applies to content, not padding, border, or margin.
You can find more information here.

div does not get centered using margin: auto in IE9

I am trying to get a centered in the space that is left empty by a sidebar. This is how I'd like it to look like:
I actually managed to make this work OK for most browsers using margin: auto for the div in question, while setting overflow: hidden:
Fiddle here
CSS
#header {
height: 50px;
background: #224444;
color: #fff;
}
#container div {
padding: 1em;
}
#content {
max-width: 400px;
margin: auto;
background: #ddd;
height: 300px;
overflow: hidden;
}
#sidebar {
float: right;
width: 200px;
background: #aaa;
height: 300px;
}
HTML
<div id="container">
<div id="header">
PAGE HEADER
</div>
<div id="sidebar">
Sidebar
</div>
<div id="content">
Centered Content
(Works everywhere but on IE9)
</div>
</div>
However, it does not work with IE9. It is strange as IE8 works OK!
I am running out of ideas, so I thought that maybe someone knows what is going on? The trick seems to work perfectly everywhere else.
NOTE: Please note that the content div should be flexible as it is in the demo. As the available space decreases, it should change size and squeeze in.
Isolate the centering from the floating
This affects IE9/10.
It works fine if the floated element is removed, or if width is used instead of max-width. The presence of floated content, combined with the use of margin:auto and max-width instead of width, appears to be confusing IE9+.
To fix this, put the centered content in a wrapper div, so that the centering of the content can be separated from the floating of the sidebar. In other words, too much is happening layout-wise in a single div, more than IE9+ can handle. So split up the #content div into two separate divs.
#header {
height: 50px;
padding: 1em;
background: #224444;
color: #fff;
}
#content-wrapper {
overflow: hidden;
}
#content {
max-width: 400px;
margin: auto;
padding: 1em;
background: #ddd;
height: 300px;
}
#sidebar {
float: right;
width: 200px;
padding: 1em;
background: #aaa;
height: 300px;
}
<div id="container">
<div id="header">
PAGE HEADER
</div>
<div id="sidebar">
Sidebar
</div>
<div id="content-wrapper">
<div id="content">
Centered Content
</div>
</div>
</div>
This tested fine in IE7/8/9/10. On a side note, because a wrapper div was added, the padding: 1em; now has to be added to each element individually.
IE is notorious for not working without proper doctypes.
Try adding the HTML5 one
<!DOCTYPE html>
Floats are a tricky business. Strictly speaking, they're only supposed to affect the inline content that flows around them, so margins acts like the floats aren't even there.
Try this instead:
#container {text-align:center}
#content {display:inline-block;text-align:left}
This should make the content box act like an inline element, and therefore appear centered in the space.
As far as I remeber I've always problems with margin:0 auto because I didn't specify width property.
So everytime you want use margin:auto you propably should write this:
#content {
max-width: 400px;
margin: auto;
background: #ddd;
height: 300px;
overflow: hidden;
width:500px;
}
or in percentage:
#content {
max-width: 400px;
margin: auto;
background: #ddd;
height: 300px;
overflow: hidden;
width:30%;
}
EDIT
If you want to create flexible layout please take a look to bootstrap and fluid grids.

IE 11: Element with min-height: 100vh will cause scrollbar

I already read a lot of posts about IE 11 with display: flex and min-height, but didn't find my answer.
I have a normal <div> with a min-height: 100vh;. In that <div> I have another element with a margin-bottom: 5px;. Now the whole outer <div> has a scrollbar and a transparent border at the bottom of 5px.
When I increase the margin, the gap at the bottom will increase the same.
Example:
<div class="layout">
<div class="panel">
Some content
</div>
</div>
body {
margin: 0;
}
.layout {
min-height: 100vh;
background: orange;
}
.panel {
margin-bottom: 40px;
background: white;
border-radius: 5px;
padding: 5px;
}
<div class="layout">
<div class="panel">
Panel
</div>
</div>
Now I made the code snipper, I see it also going wrong in Chrome.
I hope you understand me, but if you need more info please ask. I hope to find an answer!
Thank you,
Ronald.
Your issue is because of margin collapsing and it could be fixed in different ways.
Depending on your case, easiest is to use overflow: hidden for .layout:
.layout {
min-height: 100vh;
background: orange;
overflow: hidden;
}
You could also use padding-bottom on .layout instead of margin-bottom on .panel to avoid the issue with margins.
Another option could be clearfixing the .layout like so:
.layout:before,
.layout:after {
content: ' ';
display: table;
}