FAQ : Everything you wanted to know about floats but were afraid to ask. (Floats & float Bugs and Problems in IE)
IE has a few little bugs that crop up when using floats and once you understand them then you can work around them quite easily.
FAQ: The margin on a float is bigger in IE than in other browsers.
IE6 has a double margin bug on the side of a float nearest either the windows (or containers) edge. This means that the first float next to the left side or right of a window will get its right or left margin doubled. Subsequent floats are not affected.
Try this example in IE6 and then in mozilla:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css">
#floatexample {
float:left;
width:200px;
margin-left:300px;
height:200px;
border:1px solid #000;
}
</style>
</head>
<body>
<div id="floatexample">Float example</div>
</body>
</html>
You will see that in IE6 the float is nearly off the screen while in mozilla its in its correct position.
The solution is to add display:inline to the float which for some strange reason fixes the IE6 problem. “display:inline” applied to a float is a nonsense fix because you can’t actually make a float display:inline as a float always has a block display by default. This means its safe to use and will have no ill effects as other browsers just ignore the rule without ill effect.
#floatexample {
float:left;
width:200px;
margin-left:300px;
height:200px;
border:1px solid #000;
display:inline;
}
FAQ : The famous Three pixel jog:
IE6 always adds about 3 pixels of padding around floats when aligned next to static content (floats next to floats are ok and don’t have this problem which is why people will put floats together to avoid the problem.)
The solution to this is a little more complicated and relies on a trilogy of techniques.
- The first is to give the float a negative margin to pull that padding back.
e.g. on a left floated element :
* html #leftelement {margin-right:-3px}
This has to be hidden form other browsers because they would make the element too short which is why the star selector hack (* html) has been used to give styles only to IE6 (and under). (See the above FAQ on the broken box model for more info on the star selector hack.)
- The above code will make the float the correct width but if you had a margin on your static content alongside the float you would also need to reduce that by 3 pixels also. This is because IE6 will always add that 3px padding back on. Use the star selector hack as above to provide an alternative margin for IE6 on the static content.
* html #content {margin-left:212px}
- The last of the fixing techniques for the float is where the 3 pixel jog gets its name. Although we have fixed 2 issues above with floats there is one last issue that occurs only in static content next to a float where the static content is held clear of the float by margins as mentioned above.
When text in the static content grows to a point where it is longer than the float is alongside then the text in the content jogs back 3pixels because the effect of the extra padding that IE6 has applied to the float no longer takes effect. This can make the layout look a little strange.
The fix is to give the static content a width, which cures the problem, or even a height will cure the problem. However most of the time you want neither height nor width because by its very nature this static content should be in the flow and take up available space automatically. Therefore we need another hack and that is to give IE6 a height of 1%.
IE6 treats height as min-height and will automatically expand the height to accommodate content so it can safely be used. However other browsers will adhere to the height:1% so it must again be hidden from them using the star selector hack.
* html #content {margin-left:212px;height:1%}
Note that ie5 mac doesn’t like this and doesn’t need it either so for completeness you should give ie5 mac a height auto using one of the mac hacs.
e.g.
* html>body #content {height:auto}
So there you have all the answers to the 3 pixel jog float problems. Here’s an example of all the techniques wrapped into one example.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css">
#left {
float:left;
width:200px;
margin-left:15px;
display:inline;/* double margin fix for ie*/
background:red;
height:100px;
}
#content {
margin-left:215px;
background:yellow;
}
* html #left{margin-right:-3px}/* reduce the right margin to account for 3pixels*/
* html #content {height:1%;margin-left:212px}/* fix 3 pixel jog and account for 3 pixels extra padding*/
</style>
</head>
<body>
<div id="left"><p>Left float</p></div>
<div id="content">
<p>This is the static Content : This is the static Content : This is the static Content :
This is the static Content : This is the static Content : This is the static Content :
This is the static Content : This is the static Content : </p>
</div>
</body>
</html>
IE6 still has one trick up its sleeve in that if you resize the window very small then the text will drop below the float and the smaller margin will take effect. However this will only happen at smallest sizes and is possibly best ignored. (I didn’t say it was perfect did I.)
FAQ : 50% float + 50% float = 101% !
Sometimes if you put 2 or more floats side by side with percentage widths then the float drops up and down on every odd pixel, as the page is re-sized. This is a rounding bug mainly in IE6 (other browsers versions do sometimes have their own rounding bugs also) and in cases where the odd numbered pixels are rounded up then the total width becomes greater than the space allocated thus causing the float to drop.
The solution is to make one float slightly smaller so that the rounding error is negated.e.g. 49.9%.
A neater way is still to make both elements 50% (or whatever adds up to 100% exactly) and then just apply a 1px (or sometimes 2px) negative margin to the opposite side of the last float in sequence. For a float that’s floated left you could add a margin-right:-1px which will drag its right edge 1px smaller and counteract the rounding error.
FAQ : What is float drop:
No its not a dodgy advert for some drug its when two floats meet as the screen is resized or when static content meets floated content then the browsers will try and accommodate the content by looking for space wherever it can. This usually results in one of the elements dropping underneath the other one in order to find space.
Unfortunately IE will drop floats (or the content alongside) even when there is no space underneath and there is very little that can be done about it. Most times this behaviour is what you want but when you have a columnar layout you do not want any content to drop because they should remain alongside each other. Mozilla will not drop the floats in these cases because it knows better.
Again, unfortunately, IE will apply this behaviour if there are large images in the static content and the browser has been resized so the images are tight to the container and then IE will drop the whole page below the float. This can be a real nuisance if your float is very long as the content will drop all the way to the bottom.
One cure is to wrap the elements up in floats themselves but this gets very complicated quickly and doesn’t always work.
Another partial cure (which I’ll share) that hasn’t been documented anywhere except here (AFAIK). This has limited scope and can only be used in the following conditions. Where you have a left float with static content alongside then you can use this method.
You set the left float to have a negative margin the same size as its width. This takes the float completely off screen and out of the equation altogether. You then just use position:relative to move the float back into positioning. With position:relative the browsers still thinks the float is out of the way and the float drop is eliminated.
Here’s a short example for you to test. Again this only applies to IE and has limited use but worth experimenting with.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css">
#left {
float:left;
width:200px;
height:200px;
background:red;
position:relative;
margin-left:-200px;
left:200px;
}
#content {
margin-left:220px;
background:yellow;
}
img {float:left;}
</style>
</head>
<body>
<div id="left">This is the left</div>
<div id="content">
<img src="images/pmoblogoi.jpg" width="455" height="102" />
<p>This is the content : This is the content : This is the content : This is
the content : This is the content : This is the content : This is the content
: This is the content : This is the content : This is the content : </p>
</div>
</body>
</html>
Try the above code in IE. Resize the window smaller and notice that the image stays at the top of the screen. Then take out the negative margin and the left positioning and try again. As soon as you resize the window to the image then the image and text drop below the float.
Edit:
In fact the above example works better if you apply the negative margin to the right side of the float instead and don’t move it relatively at all.
e.g.
#left {
float:left;
width:200px;
height:200px;
background:red;
position:relative;
}
* html #left{margin-right:-200px;}
The above code is just given to ie using the star selector hack as IE is the only one that has problems with float drop.
One other way that may clear float drop is by adding overflow:hidden to the centre content and this in some cases will cure it and stop the content from dropping. Of course you should have fixed the 3 pixel jog first so that that problem is out of the way.
As usual trial and error is needed but with one of the methods above you can usually solve the problem.
FAQ : What is clear used for:
Clear is used to prevent elements from being displayed next to floated elements. Clear:left will ensure that the left side of the element is clear of all floats and clear:right will ensure that the right side of the element is clear of all floats. Clear:both will make sure either side is clear of all floats.
You may also often see this in some web pages:
<div style="clear:both"></div>
or
<br style="clear:both" />
What are they used for?
Well floats are basically removed from the flow so that if they are the only element in a container then that container behaves as if the float doesn’t exist. If the container has a background colour then it will not wrap the background colour around the float as it would with other static elements.
Therefore clear:both is used to provide content into the container in order to force the container to encompass the float with its background. The container now has something to get hold of and will stretch around the clear statement which by effect has cleared the float.
It is usual to place this clear:both before the closing div of the parent container. You may wonder why there are two versions - one using break and one using div. The short answer is that <br> works better in mozilla and div works better in IE. The reason being that mozilla requires the element to have height before it will clear and the break has intrinsic height.
However I offer a better solution that works for both browsers (ie and mozilla (& most others)) and simply provides one pixel content which gives the browsers something to get hold off and then uses a negative margin to kill the space that it would have made. This gives a clearing effect without adding any unwanted space to the layout.
CSS:
.clearer {
clear:both;
height:1px;
overflow:hidden;
margin-top:-1px;
}
HTML:
<div class="clearer"></div>
To finish off with here’s a short example using float to structure a layout and if you copy the following code the effects are obvious and easy to understand.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css">
#left {
float:left;
width:200px;
margin-left:15px;
display:inline;/* double margin fix for IE6*/
background:red;
height:100px;
}
#content {
margin-left:215px;
background:yellow;
}
* html #left{margin-right:-3px}/* reduce the right margin to account for 3pixels*/
* html #content {height:1%;margin-left:212px}/* fix 3 pixel jog and account for 3 pixels extra padding*/
</style>
</head>
<body>
<div id="left"><p>Left float</p></div>
<div id="content">
<p>This is the static Content : This is the static Content : This is the static Content :
This is the static Content : This is the static Content : This is the static Content :
This is the static Content : This is the static Content : </p>
</div>
</body>
</html>
overflow:hidden - used to clear floats:
You can also make floats contain their children by applying overflow other than visible to the parent which creates a block formatting context and forces the parent to acknowledge the floated children.
This doesn’t work in IE6 but for for IE6 you just need to ensure that the parent is in “haslayout mode” which can easily be tripped by supplying a dimension.
You can read more on this method here in a SitePoint article. Usually overflow:hidden is used these days but can only be used where you don’t want non visible overflow (such as in negative margins dragging an element out of the parent etc.)
If you want to clear floats without using structural mark up then have a look at the methods promoted at the PIE website . To cater for ie7 the full [URL=“http://www.tanfa.co.uk/”]clearing method should be like this:
.clearfix:after {
content:".";
display:block;
height:0;
clear:both;
visibility:hidden;
}
.clearfix {
display:inline-block;
}
/* mac hide \\*/
* html .clearfix {height: 1%;}
.clearfix {display: block;}
/* End hide */
<div id="outer" class="clearfix">
<div class="floatedstuff">
<p>Floated content to be cleared</p>
</div>
</div>
The above method works well and saves having to have unwanted mark-up in the html. I have noticed though that if the element is the last element on the page it does seem to introduce a space at the end. However that will rarely be a problem.
See this thread for a thorough dissection of the clearing methods mentioned above.
Firefox clearing all floats!
I should mention here that when you clear a float you are effectively clearing all content above the float. If you have a columnar layout then you could find that clearing an element in one column causes the clearing element to drop below all columns.
This is the correct behaviour according to the specs and one that you should be aware of. There is a solution in that you can contain the clearing effect by making sure the parent is also floated. Any clears are contained within that parent float as it can’t really clear itself.
Here is an example that demonstrates the above.
Hope that’s cleared the floats up for you!
Paul
Edit:
Note that Firefox 1.5 will now clear properly with just a simple clear:both and no height is required.