Fixed or fluid width? Elastic!

A question many web designers ask themselves each time they start working on a new project is whether the site should use fixed or fluid width. The debates on the subject are many and sometimes heated. This is not one more of those debates.

Instead I’ll explain how I combined some of the benefits of both fixed and fluid layouts when redesigning this site. The result is an elastic width layout, a concept which is not unique – you may recognise the term Elastic Design from Patrick Griffiths’ A List Apart article by that name.

For the purpose of this quick explanation I’m leaving out the header, navigation, and footer areas of the HTML structure, focusing on the remaining two column layout which consists of the #main and #sidebar div elements:

  1. <div id="wrap">
  2. <div id="main"></div>
  3. <div id="sidebar"></div>
  4. </div>

To create the two columns I’ve assigned widths to the two elements and floated them in opposite directions:

  1. #main {
  2. float:left;
  3. width:59%;
  4. }
  5. #sidebar {
  6. float:right;
  7. width:29%;
  8. }

The widths are set in percent to make both columns expand and contract as the browser window is resized.

To get some spacing between the outer edges of the columns and the edges of the main layout container (#wrap) I’ve given each column a little bit of margin. This is also specified in percent to make the margins flexible and to make it possible to accurately calculate the total width of the two columns plus their margins.

The flexible margins are what Richard Rutter referred to as “concertina padding” in a comment on my post about the redesign.

  1. #main {
  2. float:left;
  3. width:59%;
  4. margin:0 0 0 4%;
  5. }
  6. #sidebar {
  7. float:right;
  8. width:29%;
  9. margin:0 2% 0 0;
  10. }

That’s it for the column widths and margins. The layout width is now fully fluid, which can cause readability problems for people who like to make their browser windows very wide since lines of text become too long to read comfortably.

To avoid that I used the max-width CSS property to specify how wide the #wrap element can become. I could have used pixels to define a maximum width for the layout, but that would have made line lengths increase as text size is reduced and decrease as text is made larger. I wanted line length to be comfortable for reading and stay roughly the same regardless of text size. By using em instead of px as the unit for max-width, the width will depend on font size and line length will be similar no matter what size the text is.

  1. #wrap {
  2. max-width:70em;
  3. }

Then I added a couple of other declarations that may be of interest to that rule. One centres the layout horizontally, and the other inserts a vertically repeating background image to serve as a separator between the columns:

  1. #wrap {
  2. margin:0 auto;
  3. max-width:70em;
  4. background:#fff url(/i/separator.gif) repeat-y 67% 0;
  5. }

That’s it. In case you’re wondering why I didn’t use the min-width property to prevent the layout from becoming too narrow, it’s because I can’t really see a reason to. Why force people who prefer very narrow browser windows to deal with a horizontal scrollbar? Yes, the navbar will wrap in very narrow windows, but so what?

Oh, right. Just one more thing. Internet Explorer for Windows.

IE doesn’t support max-width, so I needed to find a workaround for that. I chose to use an expression, Microsoft’s proprietary CSS extension. Since expression is invalid CSS and I want my main CSS file to be valid, I put the IE stuff in a separate file and used conditional comments to make sure only IE loads the file. I also put a couple of additional fixes to take care of the IE Doubled Float-Margin Bug in the IE-specific CSS file.

  1. #wrap {
  2. width:expression(document.body.clientWidth > 900? "900px" : "auto");
  3. }
  4. #main {
  5. display:inline;
  6. }
  7. #sidebar {
  8. display:inline;
  9. }

The #wrap rule makes the width of #wrap flexible until the browser window is wider than 900px, at which point the width of #wrap is fixed at 900px. Unfortunately for IE users, this will not make the width elastic, just fluid with a maximum width. Not as neat as in modern browsers, but better than nothing.

And there you have it: elastic width with concertina padding and a maximum width. Feel free to adjust it to suit your needs.

Update: Since I wrote this article I have redesigned the site, so the CSS described here does not match what I actually use anymore.

Posted on April 25, 2005 in CSS, Usability

Comments

  1. Excellent as always. Do you have a book? I print probably 90% of the articles you write on this site. I just used your navbar tabs tutorial on a site for my girlfriend, pritchy.com.

  2. April 25, 2005 by Andrea Martines

    Since expression is invalid CSS and I want my main CSS file to be valid, I put the IE stuff in a separate file and used conditional comments to make sure only IE loads the file

    This doesn’t anyway solve the CSS validity problem if the page is viewed with IE! What about instead putting the expression code in a separate js file?

    window.onload=patchIE;
    function patchIE() {
    document.getElementById('wrap').style.width = 
    (document.body.clientWidth > 900)? "900px" : "auto";
    }
    

    Then the rest of the rules in your ie.css file could be moved at the bottom of the main.css file:

    /* Layout fix for IE */
    * html #main {
    display:inline;
    }
    * html #sidebar {
    display:inline;
    }
    ...
    

    So there’s no more need to have a non-valid css for IE. Obviously the html file will now use IE conditional comments to call the external fix script.

    I know there’s only a major conceptual objection to this method: you will have a “presentational” js, where scripting should always be kept “behavioral”. But… we can really exclude the idea of a bit of presentational scripting if our purpose is to keep together a) complete validity of our code, b) crossbrowser functionality of our complex layout, c) immunity to the browser elitism sirens?

  3. I’d argue that the expression isn’t invalid to IE, which is the only browser that should be seeing it, anyway. And why split your hacks up into more pieces than absolutely necessary?

    Also: I hate Javascript and avoid it if at all possible grin

  4. April 26, 2005 by Andrea Martines

    Su:

    I’d argue that the expression isn’t invalid to IE, which is the only browser that should be seeing it, anyway.

    The expression makes the CSS (the file ie.css, viewed by IE) non valid. C’est a dire, out of web standards.

    And why split your hacks up into more pieces than absolutely necessary?

    That’s not the case, I’ve suggested to use a file (js) instead of another file (ie.css). This method just allow to submit entirely valid code to all the browsers.

  5. April 26, 2005 by John

    Thanks Roger, now I don’t feel so bad about crawling all over your code when you relaunched this update :)

  6. I’d argue that CSS was designed to allow properties that it didn’t recognize to be ignored and that it isn’t a requirement that CSS only contain W3C defined properties. Invalid values shouldn’t create any issues in any browsers that don’t understand them.

    XHTML, on the other hand, MUST be valid by it’s very XML nature.

  7. What Jonathan said. The primary issue with behavior is that it isn’t “-behavior” and in any case isn’t particularly worse to me than Safari and Firefox preemptively supporting CSS3 properties that aren’t “standards”(read: recommendations) yet and may change in the future. The idea of standards is a bit of a convenient illusion that for some people gets in the way of simple practicality.

    What I meant by splitting the hacks up is that Roger’s implementation keeps all of the IE hacks together in one place at the moment. “This is the regular stylesheet. These are all the hacks.” Your suggestion puts some of them at the bottom of the main CSS file, and another chunk in a separate JS file. There are some hacks which have to be done inline with the regular stuff. Some others require more script calls and conditional comments, etc.
    Overall, it ends up being a matter of organization and interpretation, and what works for you. The off-hand introduction to the IE hack gave me the impression he wasn’t particularly interested in making it elegant so much as that it was a minor last-minute annoyance to be fixed.

  8. What Jonathan said, too. CSS was designed to support properties that it doesn’t understand. If the browser arrives at a value it doesn’t understand it is supposed to ignore that item.

  9. Just a minor addition to the JS solution;

    window.onresize=patchIE;
    

    In the CSS version, though, that is handled automatically, too :)

  10. April 26, 2005 by Roger Johansson (Author comment)

    Feaverish: Nope, no book. Maybe one day ;-)

    About the CSS validity and using a separate file for IE: No, moving the expression to another file doesn’t make it any more valid, but it is “valid” to IE. Yes, browsers are supposed to ignore any CSS they don’t recognise, but since I like the idea of having a hack free main CSS file and put all the IE hacks in a a separate file it’s convenient to move the expression to that file as well.

    And Su is correct in assuming that I didn’t think too much about making it elegant. Moving the expression to a JavaScript file is an option and would keep the CSS all valid, but since only a broken browser is seeing the invalid CSS anyway I think I’ll stick with the method I’ve described here.

  11. For God’s sake, what is so great using non-standard code? To make it short: It’s harmful! Support standards bodies like ISO or W3C, and get stuff like “expression” to be a part of the standard - it will be included if it’s useful!

  12. April 26, 2005 by Roger Johansson (Author comment)

    Jens: There is nothing great about using non-standard code. The only reason I’m using it is to cater for a broken, non-standard browser.

  13. A look at your source-code makes it all look very familiar, with conditional comment and all. IE-expressions tap into javascript, and won’t work if js is turned off, so the approach makes most sense as is.

    Min-width is only useful for avoiding total breakdown at a too early stage. Nothing here that will break down too early, so no need for it. Opera can override min-width in part anyway, and lots of pages around is in need of a shrink. No such problems here.

    Recommendations like CSS3 are not preemptively supported — when they have become recommendations. Browsers are recommended to implement future parts of CSS at an early stage, since nothing will become parts of a standard unless at least one browser supports it. That’s how standards are developed and tested.

    Standards are just that: standards. No need to make them rule of law. Solutions that mimic standard look and behavior in non-standard browsers are the closest we can get to following standards, as of today.

    In short: you have a well-working solution, as far as I can see. Presenting it so others may learn a thing or two, is a very good idea.

  14. Roger - sorry for having been that straightforward, but just having examined a lot of image replacement techniques (including sIFR and DIR, both using non-standard code as well) I wondered if the entire community goes crazy…

    I desperately hope us all to use reasonable solutions for all the challenges we face - there is no other way. Generally, this might just be using “MOSe” and waiting for a broader standards support, specifically, it is using alternative techniques (like SIIR or Phark for image replacement).

  15. Excellent article Roger also some excellent points made in the comments as well. I too agree with Feaverish “wheres the book” .

  16. April 26, 2005 by Andrea Martines

    Roger:

    The only reason I’m using it is to cater for a broken, non-standard browser.

    Sure, but the point is: why not using a standards-compliant solution when available to reach the same result? The hack management optimization has (imho) lower priority than standards compliance.

    Jens - I share your wonder about some kind of recent “fear of winning” in the web standards movement, leading many to stop developing solutions at 99,9% compliance with their own principles. Regarding sIFR, take a look at this Scano’s proposal to fix some non-standard feature in sIFR: Standard Flash Object Text Replacement Anyway, I think major problems of sIFR are on the usability side.

  17. April 26, 2005 by Jason

    Maybe you can explain this to me: When I tried the above design, and floated either or both of the divs, Firefox and IE take them out of the “wrap” div. So, “wrap” ends up being only 1px or so tall, and barely visible. “Main” and “sidebar” are placed below “wrap” on the page. Any suggestions on what I’m doing wrong? Thanks.

  18. April 26, 2005 by Roger Johansson (Author comment)

    Jens: No problem :-)

    Andrea:

    why not using a standards-compliant solution when available to reach the same result?

    To keep all IE hacks in one convenient place and because I simply didn’t think of using JavaScript, as you suggest. I try to minimise the time I spend working around browser bugs. Next time I may do it your way.

    Jason: Yeah I left that part out of this. You need to make the #wrap div contain the floats, either by using a clearing method on the #wrap div or by adding a clearing element after the floats. I’m using the second option here - the #footer div has a clear:both declaration.

  19. Although I’m no fan of using non-standard code just to pamper broken software, sometimes you just have to be a realist. However inexplicably, IE is still quite ubiquitous.

    Using a proprietary, but wholly unobtrusive technique like conditional comments to serve proprietary CSS to IE is definitely the best solution if you ask me. It doesn’t hurt other browsers, and the few bytes it takes in the markup is negligible, even on a very slow connection.

  20. Just my two cents worth:

    I’ve always found that using conditional comments to load seperate css files adapted to IE the number one way to go in terms of maintenance, ease of use and lack of extra headaches.

    Considering that these days, it’s possible to expect almost all popular browsers, with the exception of ie versions to support a single, hack free CSS file it seems to be a no brainer.

    Add to it that your IE users can’t “turn off” conditional comments (at least I could not) as they can Javascript and it makes no sense to not use this method on every project.

    Sure, but the point is: why not using a standards-compliant solution when available to reach the same result? The hack management optimization has (imho) lower priority than standards compliance.

    Because usability (imho) trumps them both.

    I would certainly err on the side of standards, but in this particular case, the javascript solution is crippled (can be turned off) whereas the not perfectly standard solution is not.

    As I said, to me this is a no brainer, standards compliance is not the be all and end all, especially when it only affects those already using a browser that is not compliant.

    Let’s remember that we’re making websites, not religion.

  21. April 26, 2005 by Andrea Martines

    Tommy:

    Using a proprietary, but wholly unobtrusive technique like conditional comments to serve proprietary CSS to IE is definitely the best solution if you ask me

    We all here agree that conditional comments are a good solution, if there’s no cleaner way to do our job. I was, in fact, suggesting to use them. The point was what to include with this method: an IE proprietary expression in a style sheet (kinda scripting CSS) VS a normal small js.

    But, obviously, there’s an even cleaner solution I didn’t mention before: avoid conditional comments, including a little browsercheck (for IE detecting) on top of my js file, so it can be served to all UAs. Conditional comments are useful, but in THIS case we can do it all with fully standard code. Why not? Roger has already answered.

    Dave:

    I would certainly err on the side of standards, but in this particular case, the javascript solution is crippled (can be turned off) whereas the not perfectly standard solution is not.

    That’s not correct, Dave. Turning off javascript obviously doesn’t affect the CSS rules, but the IE expression included won’t be executed. The switch option was implemented exactly for purposes like this, to avoid potentially malicious scripting activity.

    And this is also no secondary reason to adopt my solution: mixing scripting and style rules in a file lead to a potentially partial execution of that chunk of code (according to the user options, who could uncheck style and/or scripts), while keeping the script apart keep a best modularity of the components.

  22. In spanish. http://www.100px.com/articulos/nifijoniliquidoelastico/

    ;)

  23. Thanks Roger,

    This gave me a little insight in my CSS Reboot version I am creating. It was the percentages. There were kinda off and I tried something a little different, now it works both in IE and Firefox (as well as the others - but IE was the main issue).

    Thanks again! Drew Decker

  24. April 27, 2005 by John

    Thanks Roger,

    I actually looked at your technique a few weeks ago and implemented it into a site I was building. Its of course a shame that IE doesn’t support max-width. Lets hope IE7 will, and that a decent adoption rate will occur. But I’m not holding my breath. It does break down when js is turned off in IE. Well, it doesn’t really break down, it just doesn’t execute the expression.

    Thanks again.

  25. Disregarding all the comments about the non-standard code and non-valid IE-specific CSS (which I have no problem doing), this is an excellent piece of information. I’ve been a designer who would shy away from fluid layouts due to the way they look in larger browser windows. However, I find fluid layouts to be quite useful in some cases.

    Seems like hybrids are all the rage these days.

  26. Oh wow, it hadn’t even occurred to me that you could use percentages for margins.

    I ended up using ems for column widths for DigitalAdvisor. But I think percentages plus a max width, like what you’re doing, would probably work better.

  27. Great article! (as always!)

    Let’s remember that we’re making websites, not religion.

    Amen!

  28. May 2, 2005 by dan

    Jennifer: I recently read an article (I tried unsuccessfully to find it - I read too many articles) expounding guidelines for maintaining the readability of body text that suggested a column width of 30em, giving approximately 12 words per line; this provides maximum readability.
    Using ‘em’ is hardly different to using percentages, but text blocks expand much more gracefully when the text-size is increased, with no words jumping lines as you get with percentage-based column widths.

  29. Great looking site Roger. This is a great discusssion and the coments are almost as helpful as your post. I will be linking you (and paraphrasing a little) on my blog tips site

    link to my post

  30. Since I’m looking at implementing this on my redesign, I’m just now getting into the nitty gritty of your elastic setup. On IE6 Win2K (I haven’t tested any other IE versions), I get a strange effect: Fluid works as long as you don’t stretch beyond 900px. Once you reach 900 and try to resize the browser to be narrower again, it stays fixed at 900… Hmmm.

  31. May 18, 2005 by Roger Johansson (Author comment)

    J.J.: Yes, I’ve seen that. I don’t know why it does that really. And to be honest, I haven’t spent a lot of time trying to find out, so maybe that’s something i should do.

  32. J.J., Roger: Couldn’t you solve this by following Andrea Martines’ approach in using Javascript instead of a conditional comment, and add an onResize-handler? It’s going a bit crazy in IE (it’s called as soon as you click on the corner, and it’s called again and again…until you’re done resizing), but I don’t know if that’s considered “wrong”.

    I think at this point I’d reconsider using the script… :o)

    Great article, by the way, I am very tempted to use this technique once I get to redo my portfolio.

  33. May 20, 2005 by Roger Johansson (Author comment)

    I’ll look into using a script to make it smoother in IE. Not sure if it will help, and I’m not going to spend a whole lot of time on it. IE has already stolen too many months of my life.

  34. August 23, 2005 by James

    I’m a big fan of your elastic designs. I use a different method for defeating IEs bugs, however: I generate the CSS file dynamically as a JSP, changing properties based on browser detection. See my recent post.

    I find this lets you get your CSS to be valid for browsers that are less buggy, but is easier to maintain than a CSS file with lots of hacks.

  35. August 24, 2005 by Dawn

    On IE6 Win2K (I haven’t tested any other IE versions), I get a strange effect: Fluid works as long as you don’t stretch beyond 900px. Once you reach 900 and try to resize the browser to be narrower again, it stays fixed at 900… Hmmm.

    I was able to fix this by adding
    width:expression(document.body.clientWidth

  36. August 24, 2005 by Dawn

    Sorry, that should have been
    width:expression(document.body.clientWidth < 900? “100%” : “auto”);

  37. will the work around for IE still be neccessary for IE7? I can’t test in it yet because there is no german beta version for IE7.

  38. I agree with Jens that there’s nothing great with using non-standard code. I think the programming should be based on some standards to make sure it’s efficient under various browsers and various types of computers. Creativity and dystinctiveness are the designer’s matter.

  39. January 23, 2006 by Tomcy

    In a row i want to have three columns of FIXED width. Whatever content it has inside, i always want the overall layout to be constant. If the inner content in a column extends, then wrap all the contents inside itself.

  40. What do I need to do to get my header image to resize like yours does? Thank you for this article it’s great!! If anyone could post the full script/IE for detecting/dealing with the IE problem that would be greatly appreciated. I’m a newbie!

Comments are disabled for this post (read why), but if you have spotted an error or have additional info that you think should be in this post, feel free to contact me.