Rate this page

Flattr this

Automatically adjust the height of a CSS box to accommodate floated content

Objective

Background

When the height of a CSS box adjusts to fit its content, the area occupied by any floated elements is normally disregarded. This is an intended feature of the stylesheet language, needed to allow layouts such as the one below in which a floated image overlaps two paragraphs:

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

The behaviour is rather less helpful when there is not enough running text for the image to flow into. The page is then laid out in a manner that accommodates the running text, but not the floating element. This can cause the floating element to overlap with components of the page that ought to lie beneath it, such as the outer border in the scenario described below.

Scenario

Suppose that you wish to display a box containing text and an image, as in the example above, but with only one paragraph of text:

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Note how the image overlaps the outer border. Here is the relevant section of the page markup:

<div style="border: black solid thin;">
<img src="image1.png" style="float: right;">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>

You want to prevent any overlap between the outer border and the content of the box. Specifically, you want the height of the outer box to change automatically so that it is tall enough to accommodate the text and the image, but no taller.

Methods

Tested on

Chrome (9, 10, 11, 12, 13)
Firefox (1.0, 1.5, 2.0, 3.0, 3.5, 3.6, 4, 5, 7, 11)
IE (6, 7, 8, 9)
Opera (8, 9, 10, 11)
Safari (4, 5)

clear: both

One way to achieve the desired effect is to place an empty block-level element beneath the text and floating image, but within the outer box. The clear property of this element should be set to both:

<div style="border: black solid thin;">
<img src="image1.png" style="float: right;">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<div style="clear: both;"></div>
</div>

Because the empty box is not itself a floating element, it is taken into account when calculating the required height of the outer box. Its position in the markup ensures that it is placed below the text, and the value of its clear property ensures that it is placed below any floating content.

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

This method should work in any browser that supports CSS. Its main drawback is the need for an extra div element that serves no semantic purpose. This is considered undesirable because it mixes presentation with content.

Tested on

Chrome (9, 10, 11, 12, 13)
Firefox (1.0, 1.5, 2.0, 3.0, 3.5, 3.6, 4, 5, 7, 11)
IE (7, 8, 9)
Opera (8, 9, 10, 11)
Safari (4, 5)

Fails on

IE (6)

Setting overflow to hidden

An alternative method is make use of the overflow property of the outer box. Setting this to any value other than visible causes the height of any floating elements to be taken into account when calculating the required height. A value of hidden minimises the risk of unwanted scrollbars appearing:

<div style="border: black solid thin; overflow: hidden;">
<img src="image1.png" style="float: right;">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>

The effect should be similar to that of clear: both, but without the need for an empty div element that exists only for the purpose of formatting. However this method should not be used if the outer box has any relatively-positioned content that is intended to project outside its border, because such content would be truncated.

This method should work in any browser that supports CSS 2.1 or better. (The overflow property was introduced in CSS2, but it was not until CSS2.1 that it had the behaviour described here: previously it was required to do the opposite.) It is known to fail in Internet Explorer 6. If that is a concern then it can be combined with the hasLayout hack described here and here.

Tested on

Chrome (9, 10, 11, 12, 13)
Firefox (1.0, 1.5, 2.0, 3.0, 3.5, 3.6, 4, 5, 7, 11)
Internet Explorer (8, 9)
Opera (8, 9, 10, 11)
Safari (4, 5)

Fails on

IE (6, 7)

Using the :after pseudo-class

The :after pseudo-class allows extra content to be inserted into the document tree as it is rendered. This makes it possible to implement the clear:both method without there being any extra markup in the source document:

<style type="text/css">
.clearfix:after {
    content: "";
    display: block;
    clear: both;
}
</style>

<div class="clearfix" style="border: black solid thin;">
<img src="image1.png" style="float: right;">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>

This method should work in any browser that supports CSS 2 or better. It is known to fail in Internet Explorer 6 and 7, which do not support the :after pseudo-class. If this is a concern then it can be combined with the hasLayout hack noted above.

Further reading

Tags: css