Take a look at this and please explain to me why the blue box is not 100px below the red box. This doesn’t make sense to me, it seems illogical. The blue box clears the red box and then in this new vertical context, it should apply the margin in relation to the red box. It’s not even 100px below the viewport! What’s going on?
Clearing divs don’t cooperate with top margins. It’s just that way, unfortunately. This is why folks use empty divs for clearing.
Hi Rafael,
Try floating the 2nd div left.
It isn’t ignoring the topp margin, but rather it isn’t moving the element. EIther that or put an element inbetween the two divs as to act as a clearer.
Edit-Ahh…beat me
3,000th post!
The thing is, I can’t float the second one (it has to be non-floated). And what I’m looking for is an explanation for why this behaviour is so - what’s the logic behind it? I haven’t seen any rules anywhere for “in this case, margins are ignored” except for inline elements.
Generally it is a good practice to put an element between the floated content and a cleared element. I forget why though, there are a lot of articles on this but I can’t get google to work with me (I’ve read some articles)
That doesn’t sound like good practice to me - adding extra markup for no reason? Also, the “cleared element” surely is the float itself, not something else. After all, the clear
property clears floats. There’s nothing wrong with wanting to put a normal block element under a float and specify a margin to separate it.
Or, is the intention that the float should be wrapped in another element (non-floated), which clears the float using the overflow
property? I suppose that would make more sense.
Instead you can put a bottom margin to seperate them.
I used top padding in the end. I’m still not satisfied, but whatever.
If you don’t want to change/add to the HTML that is the best you are going to get (and if you don’t wnat to use bottom margin)
Hi Raffles,
You will find that when your two divs are contained within a parent then the margins will not collapse on block elements in the normal flow. This would hold true for just using a wrapper. That is why they are so commonly used.
W3C - An element that has had clearance applied to it never collapses its top margin with its parent block’s bottom margin.
In short I believe that is saying when elements are within the same parent then collapsing margin rules go into effect.
Then when you are within the collapsing margin rules you will also find that there are “No collapsing margins with Float and Clear” applied. But without float and clear you will then get [URL=“http://www.css-lab.com/misc-test/collapsing-margin.html”]“Normal Collapsing Margins”.
A parent (wrapper) div in your code will give you what you want.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>e</title>
<style type="text/css">
*{margin:0;padding:0}
#parent {
overflow:hidden;
width:100%; /*haslayout for IE*/
background:silver;
margin-bottom:50px; /*for further testing*/
}
#a {
float:right;
width:400px;
height:20px;
background:red;
}
#b {
clear:right;
height:20px;
margin-top:100px;
background:blue;
}
p {
margin:0;
padding:10px 0 0 0;
text-align:center;
font-weight:bold;
}
</style>
</head>
<body>
<div id="parent">
<div id="a">#a</div>
<div id="b">#b</div>
</div>
<p>This text is right below the parents 50px bottom margin.</p>
<p>Margins will not collapse on a block that has been cleared of the floats above when contained within a parent div</p>
</body>
</html>
The clue to this is described here in the W3C specs (highlight mine):
Computing the clearance of an element on which ‘clear’ is set is done by first determining the hypothetical position of the element’s top border edge within its parent block. This position is determined after the top margin of the element has been collapsed with previous adjacent margins (including the top margin of the parent block).
If this hypothetical position of the element’s top border edge is not past the relevant floats, then its clearance must be set to the greater of:
- The amount necessary to place the border edge of the block even with the bottom outer edge of the lowest float that is to be cleared.
- The amount necessary to make the sum of the following equal to the distance to which these margins collapsed when the hypothetical position was calculated:
* the margins collapsing above the clearance
* the clearance itself
* if the block’s own margins collapse together: the block’s top margin
* if the block’s own margins do not collapse together: the margins collapsing below the clearance
As the float is out of the document flow, the top margin of the non-floated block will collapse through the top of the parent (body in the case of your example) so the starting point for calculating how far to push the cleared element down is actually at the top of the body. If you put a border (or padding) at the top of the body, you will find the cleared div will now be 100px below this border or padding as the margin has not collapsed.
If you put a border (or padding) at the top of the body, you will find the cleared div will now be 100px below this border or padding as the margin has not collapsed.
Interesting, a 1px padding and then a negative margin to pull it back up will set the ball in motion.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>e</title>
<style>
*{margin:0;padding:0}
body {[COLOR=Blue]padding-top:1px; margin-top:-1px;[/COLOR]}
div {height:20px}
.a {
float:right;
width:400px;
background:red;
}
.b {
clear:right;
margin-top:100px;
background:blue;
}
</style>
</head>
<body>
<div class="a">#a</div>
<div class="b">#b</div>
<div class="a">#a</div>
<div class="b">#b</div>
<div class="a">#a</div>
<div class="b">#b</div>
</body>
</html>
But note that the 100px margin will not be measured from the bottom of the float, but from where it would normally act if the float was not there.
I see, and if you take the height off that float and add content then the collapsing margins become evident on the non floated div once again.
Very interesting, thanks for all this chaps. I remember reading about collapsing margins and borders now, but some of this is completely new, especially the idea of the margin pushing through the top of the body. Also thanks for the demos Ray, very useful.
So, it still isn’t possible really to specify a “gap” to exist between a float and a cleared element below it. The gap is actually created in relation to the parent. I suppose it makes sense in light of the float being removed from the document flow, a bit like an absolutely positioned element (not that I’m suggesting floats and absolute positioning are the same thing!).
So, it still isn’t possible really to specify a “gap” to exist between a float and a cleared element below it. The gap is actually created in relation to the parent.
Yes, that is the case when placing the top margin on the non floated cleared element.
However, if you were able to place the margin as a bottom-margin on the floated element then you will get what you are wanting as well.
As shown below -
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Margin between floated and non floated elements</title>
<style type="text/css">
*{margin:0;padding:0}
body {padding-top:0;} [COLOR=Blue]/*no padding needed with margin on float*/[/COLOR]
.a {
float:right;
width:400px;
background:red;
[COLOR=Red] /*height:20px; height removed for testing*/[/COLOR]
[COLOR=Blue]margin-bottom:100px; /*bottom margin on float*/[/COLOR]
}
.b {
clear:right;
[COLOR=Red]/*margin-top:100px;*/[/COLOR]
background:blue;
height:20px;
color:#FFF;
}
p {padding:0 10px 5px}
</style>
</head>
<body>
<div class="a">
<p>Float Content</p>
<p>Float Content</p>
</div>
<div class="b"><p>100px margin is in effect when used as bottom-margin on floated div above</p></div>
<div class="a">
<p>Float Content</p>
<p>Float Content</p>
<p>Float Content</p>
<p>Float Content</p>
<p>Float Content</p>
</div>
<div class="b"><p>100px margin is in effect when used as bottom-margin on floated div above</p></div>
<div class="a">
<p>Float Content</p>
<p>Float Content</p>
<p>Float Content</p>
<p>Float Content</p>
</div>
<div class="b"><p>100px margin is in effect when used as bottom-margin on floated div above</p></div>
</body>
</html>
Yeah, that’s what Ryan suggested. I’ve decided to use that now as opposed to padding on the cleared element, as it seems more logical.
Hi,
You might be interested in this old article of mine that explains what happens when you clear a float and also shows up a couple of very strange IE bugs into the mix.
The main thing to remember with margins, padding and backgrounds on static elements is that they will always slide under a float as though the float isn’t there. It’s only the foreground content that is repelled.
The top margin on an element that follows a float is applied from the containing block and not the float above it. Which as already mentioned above is that it is better to specify a bottom margin on the float instead which ensures the content is repelled the correct distance.