Wednesday, August 19, 2009

CSS Layout for 1 or 2 fixed columns, 1 fluid

If you are struggling to provide an optimum source order in your hybrid fixed- and fluid-width CSS layout, have a look at this article from A List Apart for an innovative approach that solved my problem.

Creating a CSS layout that combines one or more fixed-width areas with a fluid-width column is straight forward. Simply float your fixed-width elements, and the remaining fluid-width content (most commonly your main page content) will wrap around the element.


<style type="text/css">

#sidebar {
width:200px;
float:right;
}

</style>

<div id="wrap">
<div id="sidebar">
<p>This sidebar is 200 pixels wide</p>
</div>
<div id="main-content">
<p>This is main content and it has a fluid width</p>
</div>
</div>


The problem with this simple approach is that most of the time the above markup is sub-optimally ordered. Users with screen-readers or viewing on devices that do not support CSS with see all of your sidebar content first, which commonly includes advertising, navigation links, messages, tips and a lot of other material which is not the main content of the site. Traditional web design wisdom says the main content of your page should appear as early as possible in your markup (although some debates still rage)

If you reverse the order of the #sidebar and #main-content divs in the markup above, the sidebar will now appear below the main-content, not alongside it. This is because by default the main-content div will consume all of the space available to it. That is nearly what we want, but we want to reserve space for the sidebar.

This problem has been solved many times for both purely fixed and purely fluid layouts. Our problem results from mixing a fixed element with a fluid one.

An opposing float, as commonly documented elsewhere, will not work. The opposing float technique uses elements floated away from each other in an wrapping div. We do not know the width of the fluid element- either in percentage or pixels - so we do not have a way to constrain the width (and do not even try guessing a percentage width for reasons too numerous to list).

Absolute positioning can also be used, but fluid headers or other relative sizes can make this approach inaccurate too. For my design, a fixed height header was out of the question.

I researched the problem for a while before posing the question on the Web Standard Group mailing list. I received some replies using the above techniques but it was the technique from A List Apart by Alan Pearce which solved all of my problems. Allan's technique was novel (to me at least) - use a large border to constain the fluid content (at 100% width) and use a negative margin on the fixed width content to allow it to share real estate with the border.

An interesting side-benefit of this technique, apart from allowing properly ordered fixed/fluid hybrid layouts, is that it handily solves the issue of applying a consistent background to an entire column when the actually amount of height consumed by the CSS element can vary. The commonly accepted technique that I have seen documented uses a cleverly positioned background image on a wrapper DIV - a technique which again works great for purely fixed and purely fluid designs, but fails in a fluid/fixed hybrid.

Using the technique described by Allan, the fluid content border and sidebar background are used to provide a consistent shading to the bottom of the wrapper element no matter which content - fixed or fluid - is longer.

Finding the solution to this problem was satisfying. My main point in blogging this is to point more people in the direction of the answer; As good as the technique is the actual article is not intuitively named for this problem. Were it not for the nice people at Web Standards Group I would not have recognised it as solving my problem. Thanks WSG and A List Apart!

No comments:

Post a Comment