Fluid CSS: floating column with max-width and overflow

Ates Goral picture Ates Goral · Apr 15, 2010 · Viewed 9.3k times · Source

I'm using a fluid layout in the new theme that I'm working on for my blog. I often blog about code and include <pre> blocks within the posts. The float: left column for the content area has a max-width so that the column stops at a certain maximum width and can also be shrunk:

+----------+     +------+
|   text   |     | text | 
|          |     |      |
|          |     |      |
|          |     |      |
|          |     |      |
|          |     |      |
+----------+     +------+
    max           shrunk

What I want is for the <pre> elements to be wider than the text column so that I can fit 80-character-wrapped code without horizontal scroll bars. But I want the <pre> elements to overflow from the content area, without affecting its fluidity:

+----------+     +------+
| text     |     | text | 
|          |     |      |
+----------+--+  +------+------+
| code        |  | code        |
+----------+--+  +------+------+
|          |     |      |
+----------+     +------+
    max           shrunk

But, max-width stops being fluid once I insert the overhanging <pre> in there: the width of the column remains at the specified max-width even when I shrink the browser beyond that width.

I've reproduced the issue with this bare-minimum scenario:

<div style="float: left; max-width: 460px; border: 1px solid red">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
<pre style="max-width: 700px; border: 1px solid blue">
function foo() {
    // Lorem ipsum dolor sit amet, consectetur adipisicing elit
}
</pre>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
</div>

I noticed that doing either of the following brings back the fluidity:

  1. Remove the <pre> (doh...)
  2. Remove the float: left

The workaround I'm currently using is to insert the <pre> elements into "breaks" in the post column, so that the widths of the post segments and the <pre> segments are managed mutually exclusively:

+----------+     +------+
| text     |     | text | 
+----------+     +------+
+-------------+  +-------------+
| code        |  | code        |
+-------------+  +-------------+
+----------+     +------+
+----------+     +------+
    max           shrunk

But this forces me to insert additional closing and opening <div> elements into the post markup which I'd rather keep semantically pristine.

Admittedly, I don't have a full grasp of how the box model works with floats with overflowing content, so I don't understand why the combination of float: left on the container and the <pre> inside it cripple the max-width of the container.

I'm observing the same problem on Firefox/Chrome/Safari/Opera. IE6 (the crazy one) seems happy all the time.

This also doesn't seem dependent on quirks/standards mode.

Update

I've done further testing to observe that max-width seems to get ignored when the element has a float: left. I glanced at the W3C box model chapter but couldn't immediately see an explicit mention of this behaviour. Any pointers?

Answer

knut picture knut · Apr 25, 2010

Set margin-right: -240px; float: left; on the <pre> element to make it occupy as less horizontal space as possible and at the same time may overflow the parent <div> element with 240px. Remember to make sure that the <p> elements clears floating elements on both sides (clear: both). Complete example below:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
    "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>Solution</title>
    </head>
    <body>
        <div style="float: left; background-color: cyan; max-width: 460px;">
            <p style="background-color: magenta; clear: both;">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit. 
                Lorem ipsum dolor sit amet, consectetur adipisicing elit. 
                Lorem ipsum dolor sit amet, consectetur adipisicing elit.
            </p>
            <pre style="float: left; max-width: 700px; 
                background-color: yellow; margin-right: -240px;">
function foo() {
    // Lorem ipsum dolor sit amet, consectetur adipisicing elit
}
            </pre>
            <p style="background-color: magenta; clear: both;">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit. 
                Lorem ipsum dolor sit amet, consectetur adipisicing elit. 
                Lorem ipsum dolor sit amet, consectetur adipisicing elit.
            </p>
        </div>
    </body>
</html>