Clearing CSS floats with CSS table values (display: table)

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.

Clearing floats with 'display: table'

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;
}

View the live demo

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.

– from 17.5.3 Table height algorithms

In short, a table will always stretch in height to make room for the contents that actually determine the computation of its minimum height.

Fixing Webkit's problems

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.

One thought on “Clearing CSS floats with CSS table values (display: table)”

  1. I believe the clearing here is done via the creation of a new block formatting context [1], so I don't think it is "display:table" that contains the float, but a "implicit" "display:table-cell".

    The spec says something like this: "[display:table] can generate anonymous boxes, one of them (with display:table-cell) establishes a new block formatting context"

    This may explain the issue you're experiencing with WebKit.

    [1] http://www.yuiblog.com/blog/2010/05/19/css-101-block-formatting-contexts/

Leave a Reply

Note: Only a member of this blog may post a comment.