Godzilla

When implementing a design, a problem I encounter frequently involves floated elements within a container element breaking the borders of their container. This occurs often in lists of articles or documents that have thumbnail images floated next to their title and description, but the issue can crop up anywhere that you use floats. The following CSS and HTML is an example of this problem.

.item { border: 1px solid #000; padding: 10px; }
.item img { float: left; }
<div class="item">
<img src="godzilla.jpg" alt="Godzilla" />
<p>Godzilla is a fictional Japanese giant monster. His first film was Ishiro Honda's 1954 film <em>Gojira</em>, and since then, he has made many more appearances, and has become a pop-culture icon.</p>
</div>

When rendered in the majority of browsers, you get something that looks like this:

Godzilla may be King of the Monsters, but that doesn't mean it's ok for him to go busting through my containing div borders when I don't want him to. This is actually the intended behavior of floated elements, but in many cases this is not how you want them to behave. There are several ways to get around this sometimes annoying behavior of floats, the most common being adding a clearing element to the HTML. Until recently, I was doing this myself, using code similar to this:

<div class="item">
<img src="godzilla.jpg" alt="Godzilla" />
<p>Godzilla is a fictional Japanese giant monster. His first film was Ishiro Honda's 1954 film <em>Gojira</em>, and since then, he has made many more appearances, and has become a pop-culture icon.</p>
<div style="clear: both; height: 0; line-height: 0;"><!-- --></div>
</div>

Unfortunately, that's hardly an elegant solution as it requires adding lots of extra HTML throughout your site that serves no semantic purpose and is purely presentational. Further, modifying the HTML isn't always an easy process, particularly when dealing with a Content Management System. Luckily there is a pure CSS solution. Using the oft-ignored :after property, we can add clearing content to the container container using only CSS, removing the need for any HTML at all. This method has been around for several years in various forms (e.g., summary articles at positioniseverything and dtott) , but I largely ignored it because I thought it was easier and less complex to just use clearing divs in my HTML. This belief was at least partly true because most articles explaining this method used an overly complex version and unintuitive hacks to serve styles to buggy browsers (e.g. IE 6).

A Simpler Solution

Combining aspects of several different versions of this method, I started using the following code. This approach is the least complex and easiest way of using it that I've been able to create that works in modern browsers (and IE 6). If you're used to using clearing elements, this method may look a bit like black magic at first glance, but it's actually remarkably simple to use and can save you time and kilobytes with very little effort. I'll explain how I manage this method in large sites with thousands of lines of CSS momentarily, but first here is how the "fix" for the above example would look in your CSS:

.item:after {
content: "";
display: block;
height: 0;
clear: both;
}

This, in essence, adds a bit of null content to the bottom of the .item div. That content displays as a block with no height and clears everything around it, forcing your container to encompass any other floated content found within. When rendered in most browsers, this results in what you see below (which is identical to what you'd get using a clearing element in the HTML):

 

The Inevitable IE6 and IE7 Fix

The only snag in this method is that (surprise) IE 6 and 7 need a little help. Luckily, it's a relatively painless fix for these browsers as all they need is an explicit height to be set for the container element (1% seems to work well without causing any issues).  So, in our example, we'd simply apply a height of 1% to the .item class for IE 7 and below ONLY. For the sake of clarity, in the following code I include the IE conditional statement for IE7 and below and style tag as you would if you were placing this code in the HEAD of your document. However, it's likely easier and more elegant to serve this rule via a unique stylesheet aimed only at those specific browsers.

<!--[if lte IE 7]>
<style type="text/css">
.item {
height: 1%;
}
</style>
<![endif]-->

Switching to this method from the more intuitive practice of using clearing elements in your HTML may seem difficult, particularly if you imagine that you need to memorize these properties and sprinkle them throughout all your stylesheets alongside each class as needed. While that would certainly work, I've found a more efficient way of applying the fix where needed that, at least for me, works incredibly well. Every project I start begins with three stylesheets already created — the primary CSS file which includes various reset and generic styles, ie7.css for IE 7 and ie6.css for IE 6 (the latter two which are conditionally loaded in the HEAD of my site). At the very bottom of my primary CSS file is the clearing method from above, while each of the IE files contains the 1% height fix. As I work on a site and I run into areas that need the content clearing fix, I simply add those classes to the rule in my primary stylesheet (which I always keep at very bottom, so it's easy to find).

Once I'm ready to begin browser compatibility testing, I simply copy those same classes to the rule in the two IE stylesheets. I've found that applying the method in this way is fast and simple (far more so than adding HTML clearing elements), especially since I always know where to find the clearing rules (the very bottom of my primary stylesheet). For example, the following is the last thing found in my primary CSS file on an actual production site:

/** CLEAR FIXES --------------------------------------------------- **/
/* To completely enclose floated elements */
#footer-menu:after,
ul.primary:after,
.views-row:after,
.block .content:after,
.views-exposed-widgets-inner:after {
content: "";
display: block;
height: 0;
clear: both;
}

To ensure compatibility with earlier versions of Internet Explorer, the following is found at the very bottom of my ie6.css and ie7.css files for the same site.

/** CLEAR FIXES --------------------------------------------------- **/
/* To completely enclose floated elements */
#footer-menu,
ul.primary,
.views-row,
.block .content,
.views-exposed-widgets-inner {
height: 1%;
}

This is the easiest way I've found to completely enclose floated elements in the browsers that we support. There are even simpler methods out there involving use of the overflow property (see this article on sitepoint for an example) that are becoming popular, but they seem prone to odd behaviors like adding unwanted scrollbars or truncating images under certain conditions. In my experience, the :after method is currently the best compromise of simplicity, ease and robustness.

If you've had issues with this method or have thoughts on clearing floated elements, please leave a comment below.

Comments

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options