CSS margin terror; Margin adds space outside parent element
HtmlCssOverflowMarginHtml Problem Overview
My css margins doesn't behave the way I want or expect them to. I seems like my header margin-top affect the div-tags surrounding it.
This is what I want and expect:
...but this is what I end up with:
Source:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Margin test</title>
<style type="text/css">
body {
margin:0;
}
#page {
margin:0;
background:#FF9;
}
#page_container {
margin:0 20px;
}
h1 {
margin:50px 0 0 0;
}
</style>
</head>
<body>
<div id="page">
<div id="page_container">
<header id="branding" role="banner">
<hgroup>
<h1 id="site-title"><span><a href="#" title="Title" rel="home">Title</a></span></h1>
<h2 id="site-description">Description</h2>
</hgroup>
</header>
</div>
</div>
I have exaggerated the margin in this example. Default browser margin on h1-tag is somewhat smaller, and in my case I use Twitter Bootstrap, with Normalizer.css which sets default margin to 10px. Not that important, main point is; I can not, should not, want not change the margin on the h1-tag.
I guess it is similar to my other question; Why does this CSS margin-top style not work?. Question is how do I solve this specific issue?
I have read a few threads on similar problems, but haven't found any real answers and solutions. I know adding padding:1px;
or border:1px;
solves the problem. But that only adds new problems, since I do not want a padding nor a border on my div-tags.
There must be a better, best practice, solution? This must be pretty common.
Html Solutions
Solution 1 - Html
Add overflow:auto
to your #page
div.
And check out collapsing margins while you're at it.
Solution 2 - Html
Add any one of the following rules:
float: left/right;
position: absolute;
display: inline-block;
overflow: auto/scroll/hidden;
clear: left/right/both;
This is caused by collapsing margins
. See an article about this behavior here.
According to the article:
> The W3C specification defines collapsing margins as follows: > > “In this specification, the expression collapsing margins means that adjoining margins (no non-empty content, padding, or border areas, or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin.”
This is also true for parent-child elements.
All the answers include one of the possible solutions:
> There are other situations where elements do not have their margins collapsed: >
-
floated elements
-
absolutely positioned elements
-
inline-block elements
-
elements with overflow set to anything other than visible (They do not collapse margins with their children.)
-
cleared elements (They do not collapse their top margins with their parent block’s bottom margin.)
-
the root element
Solution 3 - Html
Problem was the parent not taking into account children for height. Adding display:inline-block;
did it for me.
Full CSS
#page {
margin:0;
background:#FF9;
display:inline-block;
width:100%;
}
Solution 4 - Html
Just add border-top: 1px solid transparent;
to your #page
element.
From w3.org
>Two margins are adjoining if and only if:
>- no line boxes, no clearance, no padding and no border separate them
Solution 5 - Html
Add the following rule:
overflow: hidden;
This is caused by collapsing margins. See an article about this behavior here.
According to the article:
> If a parent element does not have any top padding or less top margin then its first child, then elements are rendered in a way that makes the parent element appear to have the child element's margin. So this can happen anywhere on a page where these conditions are met, but it tends to be most obvious at the top of a page.
Solution 6 - Html
The solutions in the other answers didn't work for me. Transparent borders, inline-block, etc., all caused other problems. Instead, I added the following css to my ancestor element:
parent::after{
content: "";
display: inline-block;
clear: both;
}
Depending on your situation, this may cause its own problems because it adds extra space after the last child element.
Solution 7 - Html
#page {
overflow: hidden;
margin:0;
background:#FF9;
}
Solution 8 - Html
My approach when I was making styles for XenForo 2.1, but it should be useful for you: (Please replace those LESS variables to your actual values. Also, the absolute value of minor margins shall be as same as the height of before-after pseudo elements.)
// The following two lines are to avoid top & bottom fieldset borders run out of the block body.
// (Do not tweak the CSS overflow settings, otherwise the editor menu won't be float above the block border.)
&:before {content: "\a0"; display: block; width: auto; margin-bottom: floor(-1 * @xf-lineHeightDefault * @xf-fontSizeSmall - @xf-borderSizeMinorFeature);}
&:after {content: "\a0"; display: block; width: auto; margin-top: floor(-1 * @xf-lineHeightDefault * @xf-fontSizeSmall - @xf-borderSizeMinorFeature);}