I've just finished to upload my test on complex floats. Here are the screenshots taken from various versions of Internet Explorer:
Internet Explorer 6

Internet Explorer 7

Internet Explorer 8

I've just finished to upload my test on complex floats. Here are the screenshots taken from various versions of Internet Explorer:



Clearing floated images can actually be a tedious task. Let's say that you have a blog with this post structure:
<p><img src="float.png" alt="Test image" class="alignleft" />Lorem ipsum dolor...</p> <p>Paragraph after the float.</p>
The class .alignleft is as follows:
.alignleft {
float: left;
margin: 3px 5px 0 0;
}
Since you don't know in advance the dimensions of each floated image, it's likely that you'll end up with both paragraphs surrounding the image, because you don't know in advance how much content will be contained in the first paragraph either. With CSS, you can add the following class to the paragraph containing the image:
.clear {
overflow: hidden;
height: 100%;
}
It works but it's clunky, in the sense that you have to manually add the above class every time a paragraph contains a floated image. We can automate this process with jQuery, like so:
$(document).ready(function() {
$('img.alignleft').parent().addClass('clear');
});
For each instance of the .alignleft class, the parent element is automatically cleared with the
.clear class. Do more with less. You can see the final result
here.
In the CSS specifications, the shrink-to-fit algorithm applies to floats, tables and absolutely positioned elements without a stated dimension (usually a width). In simple terms, when one of these elements doesn't have a stated dimension, its actual dimension is given by the amount of content contained in the element itself, plus any border, margin or padding declaration which will be added to the sum in order to determine the actual size of the element. For example, if you have a markup like this:
<p><span class="alignleft">Test</span>Content</p>
with the following styles:
span.alignleft {
float: left;
background: yellow;
border: 2px solid orange;
padding: 4px;
}
the actual dimension of the floated element will be determined by 1) the content of the element; 2) the border declaration; 3) the padding declaration. I've summarized most of the possible combinations on this test page. Alan Gresley made some interesting tests here.
This post describes a new way of clearing floats by using CSS table values. The technique provided below is inspired by the famous article of John Gallant and Holly Bergevin on the Easy Clearing method.
Let's say that we have the following markup:
<div id="container"> <img src="float.png" alt="Float" class="float" /> Filler text. </div> <div id="clear">Cleared text.</div>
with the following styles:
#container {
width: 50%;
padding: 1%;
background: aqua;
}
.float {
float: left;
margin: 0.2em 0.3em 0 0;
}
#clear {
width: 50%;
background: lime;
padding: 1%;
}
As you will see, the floated element overflows its container because there is no clear property applied
to the #clear element. We can easily overcome this problem by adding a special class to the container with
a single CSS declaration:
.clearfix {
display: table;
}
This solution works well in all supporting browsers (Internet Explorer 8, Firefox, Opera) with the exception of Webkit-based browsers (see later in this post). According to what is stated in the CSS specification, a table computes its height in a peculiar way. Specs say:
The height of a table is given by the 'height' property for the 'table' or 'inline-table' element. A value of 'auto' means that the height is the sum of the row heights plus any cell spacing or borders. Any other value is treated as a minimum height. CSS 2.1 does not define how extra space is distributed when the 'height' property causes the table to be taller than it otherwise would be.
In short, a table will always stretch in height to make room for the contents that actually determine the computation of its minimum height.
In Safari and Chrome, the element after the float is wider than usual, This is probably due to the fact that this element is actually a block-level element, so its width is computed differently.
Keep in mind that once declared an element as a table, its width is partly determined by the table-layout property that
is set to auto by default. Anyway, Safari and Chrome need only the following declaration that will be applied to the
affected element:
#clear {
display: table;
}
We've simply turned this element into a table, so that its width is computed correctly. We can give separate styles to Safari and Chrome by using JavaScript, as shown below.
var ua = navigator.userAgent.indexOf("AppleWebKit");
if(ua) {
var head = document.getElementsByTagName("head")[0];
var link = document.createElement("link");
link.setAttribute("href", "webkit.css");
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.setAttribute("media", "screen");
head.appendChild(link);
}
This JavaScript snippet search for an occurrence of the string AppleWebKit inside the
userAgent property of the navigator object. If there is a match, then it creates
a link element that points to a style sheet and attaches it to the head element.
Reading this article, I was struck by the fact that it's claimed that a container hosting floats is self-cleared by the overflow property. Actually, this is not correct. Instead, it should be said that the overflow property allows the container to contain floats, provided that no actual height has been specified on it. The question is: why this happens? Usually, to achieve this goal a coder specifies overflow: hidden on the container itself. If you set a background color on the container, you will see that color stretching until it contains all floated elements. The answer to our question lies not in the overflow property itself, but in the way a browser handles floats. When you turn an element into a float, vertical space collapses. That's why without the overflow property our container is not able to contain floats, because its vertical space is collapsed due to the action of its floated children. Using the overflow property, you're actually forcing the browser to recalculate the amount of vertical space inside the container so that its height now can contain floats. Without this property, a browser still uses its default algorithms to handle vertical space during floating (this is called float damage in the Firefox's source code jargon).
I'm going to develop a web-based application for domestic use containing a database for all our DVDs. In that vein, I'd like to mention here a little problem occurred during the creation process of the markup used for displaying search results. The question is: floats or tables? Since I have to deal with items like director, year, actors and so on, using floats actually involves a markup like the following:
<ul class="dvd-info">
<li>
<div class="dvd-item">
<h4>Director</h4>
</div>
<div class="dvd-content">
<p>Ridley Scott</p>
</div>
</li>
<!-- more items here -->
</ul>
The CSS would be something like:
ul.dvd-info {
width: 100%;
margin: 0 0 0.4em 0;
padding: 0;
list-style: none;
}
ul.dvd-info li {
height: 100%;
overflow: hidden;
margin-bottom: 4px;
}
ul.dvd-info li .dvd-item {
float: left;
width: 25%;
text-align: right;
}
ul.dvd-info li .dvd-content {
float: left;
width: 70%;
padding-left: 0.3em;
}
The problem with this approach is that we're actually dealing with a semantic relationship between items (e.g. "Director" and "Ridley Scott") that will be completely lost if we use the aforementioned markup and floats. In fact, we should use a table heading associated with a table cell. This approach also makes our content easier to navigate for assistive technologies that use keyboard shortcuts to extract and navigate page contents. In this case, I think, using a table is the right choice.
Containing CSS floats can be a really tedious task. Basically, every container with floats should have a rule like the following:
.clearfix {
overflow: hidden;
height: 100%; /* IE6 */
}
But with jQuery we can easily avoid to add this class to the markup with a few lines of code:
$(document).ready(function() {
$('*').each(function() {
var $element = $(this);
if($element.css('float') !== 'none') {
$element.parent().addClass('clearfix');
}
});
});
That's all! By doing so, we keep our markup intact and we spare a lot of time! Do more with less: that's jQuery's motto. Isn't it amazing?