Fluid, Elastic, Fantastic!

Alert! Because you are viewing this page in an old, faulty version of Internet Explorer, the illustrations and code below may not render properly. I recommend that you upgrade to IE8, or use Firefox.

A fundamental question when creating web pages is whether the layout will have a fixed width or whether it will be able to expand and contract depending on factors such as the width of the browser window (or viewport). Fixed-width, pixel-based layouts are predictable but not very adaptable to changing browser conditions. Fluid (or liquid) layouts—even with a minimum and maximum width set—are harder to control, especially if the design requires features like a full-width header image. Em-based designs—especially when combined with some fluid elements—in a sense combine the both of best worlds, as I'll demonstrate here.

In an em-based design, both text and layout dimensions are measured in ems. An "em" is a relative unit whose length is determined by an element's font-size. If the font-size is set at 16px, then 1em is equal to 16px. This measurement can be used for other elements, like the page wrapper. So a typical wrapper style might include the following:

#wrapper {
    width: 46em;
    margin: 0 auto;
}

This setting will create a centered, fixed-width design, but with the difference that, if the user increases the text size, the wrapper will also grow proportionately. This is much nicer than having text reflowing with every resize.

View Example 1

However, at some point the wrapper will become wider that the viewport, meaning that the user will need to scroll horizontally to view content, which is not very good.

To avoid this, add a max-width to the wrapper, like so:

#wrapper {
    width: 46em;
    margin: 0 auto;
    max-width: 94%;
}

That maximum could be set in ems, but I find a percentage better, as you don't know how wide the user's viewport will be.

View Example 2

Max-width prevents the layout getting too wide when resized, but what if the user's viewport is narrower than 46em—either to start with, or if the user reduces the width?

Answer: if you set the width of the wrapper's contents in percentages, the wrapper will contract horizontally as the viewport narrows. For example, if a #content div is placed within the wrapper and sized to width: 100%, the layout will narrow as the viewport is narrowed:

<div id="wrapper">
    <div id="content">
        <p>Content here...</p>
    </div>
</div>
#content {
    width: 100%;
}

View Example 3

Of course, columns can be floated and sized in percentages as well, such as:

#col1 {
    width: 60%;
    float: left;
}

#col2 {
    width: 30%;
    float: right;
}

View Example 4

That is the essence of a "fluid elastic" layout: elastic expansion until a max-width is reached, and fluid contraction as the viewport is narrowed.

Further Considerations

This kind of expanding and contracting layout may not seem very image-friendly. Background images don't scale, so you will need to consider their use carefully. A vertically repeating image on the wrapper, for example, will need to be wide enough to accommodate the widest screens.

Embedded images can also be a problem. If you have a wrapper-width header image sized in pixels, for example, it will either be too narrow when the text size is increased or too wide if the viewport is narrowed. A nice solution to this is to give the image a percentage width:

#header {
    width: 100%;
    padding-bottom: 1em;
}

#header img {
    vertical-align: bottom;
    width: 100%;
}

Scale the viewport up and down and watch the header image magically scale! I've also placed images within the columns, also set to width: 100%.

View Example 5

Normally, you would want text in the header as well. It would be easy to make this part of the image, but ideally it should be real text. Here is one way to do that:

#header {
    position: relative;
    min-height: 3em;
}

#header h1 {
    position: absolute;
    top: 50%;
    left: 1em;
    font-size: 2em;
    margin-top: -1.8em;
    line-height: 3em;
}

The H1 element is positioned absolutely in relation to the #header div, and vertically centered with top: 50% and a negative top margin. If you scale the example below in a browser, you'll see that the header text stays vertically centered at all sizes.

I also added a min-height to the #header div to make for a better appearance if images do not load—at least in decent browsers. (If images don't load, it's good to have text appear, and Alt text doesn't cut it for me. Search engines will pick up an H1 element that is pulled off screen with a negative margin, but that won't help users for whom images don't load.)

View Finished Layout

Browser Blues

The layouts shown above only work partially in IE6 and below. The layout does scale on resize, but neither recognizes the max-width setting nor reflows when the viewport is narrowed. Well, this behavior is consistent with fixed width design anyway, so it's no big drama. Just another reason to upgrade (or to check out a JavaScript fix or two or three [discussion here] or four).

Also, IE6 and 7 do not always handle the image scaling too well, sometimes creating jagged or blurry results—particularly if the image displays text or vector art. There are fixes for image scaling in IE, the simplest being to insert this code into your (preferably IE-specific) stylesheet:

img {
    -ms-interpolation-mode: bicubic;
}

Other solutions are discussed elsewhere, such here, here and here.

  • Twitter
  • Digg
  • StumbleUpon
  • Facebook
  • Ping
  • Mixx
  • DZone
  • Google
  • DesignBump
  • DesignMoo
  • DesignBuzz
  • Delicious
  • Reddit
  • Technorati
  • Evernote
  • FriendFeed
  • Email

Acknowledgements & Links


Leave a Comment

Feel free to comment. If you can improve on this post, your comments will be included, along with your name and a link to your website. (Comments are moderated, so spammers… just don't bother.)


What Now?

Search all Entries | Ebooks by Books for Learning | Services