views:

628

answers:

5

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?

A: 

Is this what you are trying to achieve?

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd"&gt;

<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>untitled</title>
    <meta name="generator" content="TextMate http://macromates.com/"&gt;
    <meta name="author" content="Stephen Carr">
    <!-- Date: 2010-04-15 -->
</head>
<body>
    <div style="max-width: 460px; border: 1px solid red;float: left; ">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
        <pre style="max-width: 700px; border: 1px solid blue; float: left;">
            function foo() {
        // Lorem ipsum dolor sit amet, consectetur adipisicing elit
        }
        </pre>
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
    </div>
</body>
</html>

EDIT: This version better demonstrates what I think you are trying to acheive:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd"&gt;

<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>untitled</title>
    <meta name="generator" content="TextMate http://macromates.com/"&gt;
    <meta name="author" content="Stephen Carr">
    <style type="text/css" media="screen">
        .clearfix:after {
            content: ".";
            display: block;
            clear: both;
            visibility: hidden;
            line-height: 0;
            height: 0;
        }

        .clearfix {
            display: inline-block;
        }

        html[xmlns] .clearfix {
            display: block;
        }

        * html .clearfix {
            height: 1%;
        }
    </style>
</head>
<body>


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

        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
    </div>



    <div style=" border: 1px solid red; white-space: pre-line">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>

    </div>

</body>
</html>
Simon
Sorry, but what is this exactly? You've just enclosed the non-working example I gave inside an HTML body. It still doesn't work. Am I missing something?
Ates Goral
I've only tested in Firefox but the code I attached is not the same as yours and it demonstrates your desire for "the <pre> elements to be wider than the text column".Notice the float left on the <pre>?
Simon
But the text column doesn't shrink beyond a certain limit. That's the whole thing. I need the content to shrink while the `<pre>` protrudes out.
Ates Goral
The content isn't going to shrink because you've indicated it can use up to 460px. The content in a <div> will fill the div unless you tell it not to, in other words it's going to take up 460px it will not shrink from this if the content is making use of the width. If you change the div to:<div style="width: 50%; max-width: 460px; border: 1px solid red;float: left; ">Giving it a 50% width then it will fill 50% of the screen at all times unless the max-width exceeds 460px. The <pre> will protrude beyond this as my original example shows. Full code: http://pastebin.com/2eHaGA7f
Simon
Also, if you weren't using floats and the <div> was displaying as a normal block element it still would not shrink beyond a certain width in most browsers. Seems with the example text you have given the narrowest FF goes is ~480 and the narrowest Safari goes is ~390. Firefox window will go narrower than that but it clips content, Safari doesn't seem to want to physically want to go smaller than ~390 though.
Simon
A: 

CSS:

pre {
    display: inline-block;
}

Works for Chrome and FireFox, which makes me think it will work on atleast Opera, Safari and IE8 also.

If this breaks IE6 you can use this selector to hide the rule from the browser:

div > pre {
    display: inline-block;
}

In your example (with extra characters added):

<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; display: inline-block;">
function foo() {
    // Lorem ipsum dolor sit amet, consectetur adipisicing elit dfsf sdf sdf sdf sdf
}
</pre>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
</div>
Finbarr
No luck :( The content doesn't shrink. Try shrinking the browser width to something like 250px and you'll observe that the text passages do not wrap to 250px.
Ates Goral
I don't think there is any way you can achieve this without the use of Javascript - because of the max-width declaration. Pseudo: On load and when window is resized { if window width is less than max-width { set max-width to window width } }. And besides, very few people have screens that narrow.
Finbarr
Smartphone users typically have very narrow screens :) I'm particularly interested in finding out why `max-width` and `float: left` don't play out well together. You'll see that when the `float: left` is taken out, shrinking starts working fine...
Ates Goral
`max-width` works different for floated and block level elements because floated elements try to take up as little horizontal space as possible, whereas block level elements try to take up as much horizontal space as possible.
Finbarr
A: 

This might work

pre {
  position:relative;
  float:left;
  z-index: 1;
}

position relative makes the pre "pop out" of the dimensions of the column without removing it from the document flow, and float should adjust the width of teh pre to contain all its content.

wheresrhys
The problem is with the `<p>` elements not obeying `max-width` when I have inline `<pre>` elements that protrude.
Ates Goral
+1  A: 

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"&gt;
<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>
knut
Thank you sir. I've just become slightly more enlightened!
Ates Goral
+1  A: 

I think this ought to do what you're looking for, but you might need to tweak it slightly to get it to work in situ.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
<html>
    <head>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
        <title>Test</title>
        <style type="text/css" media="screen">
            body
            {
                margin: 0;
                padding: 0;
            }
            #wrapper
            {
                float: left;
                width: 100%;
            }
            #content
            {
                float: left;
                width: 100%;
                max-width: 500px;

                margin: 0;
                padding: 0;

                font-family: "Trebuchet MS", sans-serif;
                font-size: 12px;
            }
            #content-pad
            {
                margin: 50px;
                padding: 50px 0 40px 50px;
                background-color: #CCC;
            }

            p, pre
            {
                margin: 0 50px 10px 0;
                line-height: 1.6em;
            }

            pre
            {
                padding: 20px;
                width: 560px;

                background-color: #333;
                color: #FFF;
            }
        </style>
    </head>
    <body>
        <div id="wrapper">
            <div id="content">
                <div id="content-pad">
                    <p>Fusce euismod nunc vitae orci vestibulum adipiscing. Nam id quam libero, sed convallis elit. Etiam interdum, urna et imperdiet euismod, nisi erat commodo elit, sed convallis magna est quis sem. Fusce tempor aliquet est, et ornare eros vulputate et. Vivamus arcu augue, pretium vel fermentum in, gravida sed elit. Vestibulum ut ligula ac quam hendrerit ullamcorper. Phasellus id justo augue. Integer a eros ante. Vivamus sapien mi, placerat a viverra pharetra, dignissim sit amet ipsum. Fusce nunc nunc, tempus ut aliquet sit amet, consectetur sed quam. Cras ligula enim, bibendum eget luctus a, convallis sit amet nisl. Nullam in quam in lectus faucibus lobortis vel pulvinar ante.</p>
                    <pre>Here is some code!
We're going to make sure that it has a full eighty characters to play in.
12345678901234567890123456789012345678901234567890123456789012345678901234567890</pre>
                    <p>Nullam in sapien vitae dui tincidunt elementum. Curabitur condimentum vulputate sem ornare pharetra. Fusce in dolor eget neque viverra sagittis a a orci. Vivamus blandit leo eget orci viverra quis hendrerit velit tempus. Donec in erat risus. Nullam scelerisque faucibus ante, ultricies tristique dolor laoreet sit amet. Duis sit amet tortor dolor, vel interdum ipsum. Sed sed nibh vel ipsum commodo cursus. Proin fermentum nunc in velit tincidunt imperdiet sit amet nec neque. Suspendisse neque ante, luctus sit amet pulvinar eu, congue laoreet magna. Aenean sit amet porttitor quam. Mauris hendrerit vulputate tempus. Curabitur mauris magna, laoreet congue rutrum condimentum, condimentum in sapien. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
                </div>
            </div>
        </div>

        <!-- this next element just maintains the margin properly -->
        <div style="clear:both; height: 0; overflow: hidden;"></div>
    </body>
</html>
icio
@icio: Thanks for the effort! While your solution seems to achieve what I was asking for, @knut's answer solves my problem by just the addition of two additonal CSS rules.
Ates Goral
@Ates Goral: My pleasure. Might I add that the `#content-pad` element isn't necessary for the `pre` to stick out, it's purely there for aesthetic reasons.
icio