Pup's Box Flow Hack, Rev 2

Making boxes flow around floats using CSS.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque arcu metus, mattis ut, blandit non, venenatis non, sem. Etiam molestie luctus ante. Lorem ipsum dolor.

Curabitur tincidunt mattis pede. Donec est ante, mattis eget, hendrerit nec, facilisis quis, wisi. Donec mollis nulla sit amet diam. Nunc porta tellus eu lacus.

Look at this silly nonsense.

The blue boxes are floated, the orange boxes are not. As expected, the text in the orange boxes flows around the blue box. But notice how the orange boxes extend behind the floated blue box? In certain situations, this behavior can be annoying.

Imagine if these orange boxes were posts on a messageboard, and the blue box was an ad. You wouldn't want your posts running behind your ad.

The typical way to deal with this challenge is to declare a side margin for all the orange boxes on the page, leaving room for the blue box in the resulting gutter. However, this approach reduces the available width for orange boxes since the gutter runs the full length of the containing block. You must also know the width of the floated element beforehand in order to set the margin properly.

The goal of this CSS hack is to make entire boxes, including borders and background, flow around a floated element of unknown width.

Engage hack.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nulla at pede. In hac habitasse platea dictumst. Vestibulum porttitor malesuada ante. Aenean orci. Suspendisse potenti. Aenean sed neque in diam lobortis ultricies. Vestibulum eget libero. Vivamus tincidunt purus consequat nunc. Fusce ut ipsum eget mauris faucibus euismod. Duis odio. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec metus. Donec eu pede quis ipsum ullamcorper tempor.

Proin semper, diam vel pretium pharetra, odio quam tristique felis, vel commodo arcu quam eget eros. In vitae sem sit amet sapien egestas vulputate. Nullam pellentesque magna vel arcu. Vivamus consectetuer turpis sit amet nibh. Nam ac lacus. Nulla viverra. Nulla nec felis id metus eleifend varius. Etiam nec orci id sapien tempor dapibus. Aliquam erat volutpat. Nulla eget mauris sed leo sollicitudin malesuada. Donec vehicula laoreet purus.

Much better.

The orange boxes now flow around the blue boxes.

How it's done

Let's jump straight to the finished CSS. Later, I'll go into more detail about what I'm doing and why I'm doing it.

The orange boxes are divs with a class name of box. The orange boxes contain various elements such as paragraphs and preformatted text.

First, set overflow to auto. This takes care of Firefox and Opera 8+. Next, set height to 1%. This takes care of IE 5+ PC. Add two simple CSS hacks to protect IE 5 PC and Opera 5 from themselves, and you're done.

Code

div.box {
  overflow/**/: auto;
  \height: 1%;
}

View Demo

Explanation

Background

Normally, only inline content flows around a floated box and the borders and backgrounds of the box next to the float is drawn as if the float isn't there. So you're left with text that flows nicely, but backgrounds and borders that run behind the floated elements. There are plenty of other people who can explain the details, so I won't bother. My job is to change this behavior using a few CSS tricks.

In a perfect world, we'd set div.box's display property to inline-block and be done with it. Inline-block is exactly what we need here, but we have to avoid it due to poor browser support. The main culprit is Firefox, whose support for inline-block--including -moz-inline-block and -moz-inline-box--is very buggy. The good news is there are other options. Let's get started.

Step 1

Set div.box's overflow property to auto to make Firefox and Opera work.

Explanation

Setting the overflow to auto establishes a new block formatting context for div.box. According to the CSS 2.1 specs, this means the element must not overlap any floats in the same context.

Code

div.box {
  overflow: auto;
}

Status

Firefox and Opera 8+ now work. Other browsers still fail gracefully, meaning the orange boxes render in their default state.

Aliquam gravida neque ac risus. Aliquam erat volutpat. Maecenas vitae augue. Curabitur lorem arcu, mollis at, faucibus at, mollis aliquet, dolor. Donec commodo massa nec odio. In erat lorem, dictum id, pellentesque vitae, commodo vitae, ipsum. Vestibulum a augue. Suspendisse potenti. Nam porta viverra augue. Donec sed nunc a libero tempus tincidunt. In a ante. Nullam mauris lectus, blandit a, sodales vel, venenatis ut, lectus. Mauris fermentum est id ipsum. Aliquam erat volutpat. Nam hendrerit.

Phasellus at tellus vitae sapien facilisis tincidunt. Integer dignissim est ac wisi sodales tristique. Ut magna. Nunc eu metus a est bibendum cursus. Sed sollicitudin auctor nisl. Vestibulum felis urna, semper in, ullamcorper vitae, facilisis eget, dolor. Morbi volutpat risus sit amet tortor egestas dictum. Aenean bibendum dui eget turpis. In volutpat pede vel nisl. Fusce lacinia. Morbi gravida tellus at lorem.

Step 2

Set div.box's height property to 1% to make IE work.

Explanation

Setting height to 1% gives div.box layout in IE, which is very similar to giving it a new block formatting context. This means it won't overlap any adjacent floats in the same context.

Code

div.box {
  overflow: auto;
  height: 1%;
}

Status

Now IE 5.5+ now works. Firefox and Opera 8+ still work. However, IE 5 PC and Opera 5 now fail catastrophically. Other browsers fail gracefully.

Step 3

Use two simple CSS hacks to fix IE 5 PC and let Opera 5 fail gracefully.

Explanation

IE 5 doesn't like an overflow of auto when used in conjunction with a height of 1%. It completely hides the content of the orange boxes. By targetting this specific browser version with a comment hack, we can make it ignore the overflow property. Simply put /**/ after the overflow property and IE 5 PC is working once again.

Opera 5 doesn't like a height of 1% at all. It renders the orange boxes only a few pixels high and all the content is overlapping and unreadable. Luckily we can specifically target Opera 5 with a simple escape character hack. Putting a backslash in front of the height property makes Opera 5 ignore it and allows it to fail gracefully once again.

Code

div.box {
  overflow/**/: auto;
  \height: 1%;
}

View Demo

Status

Working in Firefox, Opera 8+, and IE 5+ PC. Other browsers fail gracefully.

Sed non sem. Morbi purus odio, sodales quis, pulvinar in, ullamcorper sollicitudin, lectus. Praesent nec ante nec nisl hendrerit tincidunt. Aliquam risus odio, tempor non, dictum ut, auctor non, risus. In nec nulla eu urna aliquet volutpat. Morbi vel ipsum sit amet sem pulvinar pulvinar. Integer at est eu augue tincidunt fermentum. Donec a urna. Maecenas pretium nulla eget libero. Duis tristique lacus egestas est. Pellentesque vestibulum aliquam lectus. Ut sollicitudin. Pellentesque laoreet sollicitudin neque. Suspendisse pharetra. Sed eu eros nec nibh congue dignissim. Maecenas tempus est.

Conclusion

That's pretty much it. Just a few lines of CSS. I tried to keep the CSS compliant and forward-compatible.

Browsers Known to Work

  • Firefox 1.0 and higher
  • IE 5 PC and higher
  • Opera 8 and higher
  • Safari 2 and higher

Untested Browsers (a little help?)

  • Safari 1 and earlier

Browsers Known to Fail Gracefully

  • Opera 7 and earlier
  • IE 4 PC and earlier
  • IE 5 Mac

Notes

Thanks to Mike and the Shack for helping me test.

This was named as the "Top CSS hackery" in the Top 20 of 2005 list on Web-Graphics and blog.html.it.

Please drop me a line at john.brooks@gmail.com if you have any questions, comments, or suggestions.

- Pup

Updates

April 20, 2007

I stumbled on this new method by accident while working on another site. Apparently overflow: auto; does everything i want it to do in Firefox and Opera. This eliminated the need for the entire second declaration and vastly reduced the size of the code. The only downside is the loss of Opera 7 support, but I think that's an acceptable tradeoff.

For posterity's sake, here's what the CSS from first revision looked like.

div.box {
  height: 1%;
  display: table;
}

div.box p:after {
  display: block;
  line-height: 0;
  height: 0;
  visibility: hidden;
  content: "- - - - - (repeated)";
}

July 25, 2006

With the revelation that IE applies display: table; to elements that have layout, the hack was greatly reduced in size and complexity by eliminating the need for an IE-specific declaration. This is the first code change since it was released in January 2005

For posterity's sake, here's what the CSS from the original hack looked like.

div.box {
  display: table;
}

* html div.box {
  display: inline-block;
  width: 100%;
  wid\th: auto;
}

div.box p:after {
  display: block;
  line-height: 0;
  height: 0;
  visibility: hidden;
  content: "- - - - - (repeated)";
}
Back to Pup, Inc.