Intricate Fluid Layouts in Three Easy Steps by Nate Koechley
The Year of the Script may have drawn attention away from CSS but building fluid, multi-column, cross-browser CSS layouts can still be as unpleasant as a lump of coal. Read on for a worry-free approach in three quick steps.
The layout system I developed, YUI Grids CSS, has three components. They can be used together as we’ll see, or independently.
The Three Easy Steps
- Choose fluid or fixed layout, and choose the width (in percents or pixels) of the page.
- Choose the size, orientation, and source-order of the main and secondary blocks of content.
- Choose the number of columns and how they distribute (for example 50%-50% or 25%-75%), using stackable and nestable grid structures.
The Setup
There are two prerequisites: We need to normalize the size of an em and opt into the browser rendering engine’s Strict Mode.
Ems are a superior unit of measure for our case because they represent the current font size and grow as the user increases their font size setting. This flexibility—the container growing with the user’s wishes—means larger text doesn’t get crammed into an unresponsive container. We’ll use YUI Fonts CSS to set the base size because it provides consistent-yet-adaptive font-sizes while preserving user control.
The second prerequisite is to opt into Strict Mode (more info on rendering modes) by declaring a Doctype complete with URI. You can choose XHTML or HTML, and Transitional or Strict. I prefer HTML 4.01 Strict, which looks like this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">- Source: /code/intricate-fluid-layouts/1.txt
Including the CSS
A single small CSS file powers a nearly-infinite number of layouts thanks to a recursive system and the interplay between the three distinct components. You could prune to a particular layout’s specific needs, but why bother when the complete file weighs scarcely 1.8kb uncompressed? Compressed, YUI Fonts and YUI Grids combine for a miniscule 0.9kb over the wire.
You could save an HTTP request by concatenating the two CSS files, or by adding their contents to your own CSS, but I’ll keep them separate for now:
<link href="fonts.css" rel="stylesheet" type="text/css"><link href="grids.css" rel="stylesheet" type="text/css">- Source: /code/intricate-fluid-layouts/2.txt
Example: The Setup
Now we’re ready to build some layouts.
Step 1: Choose Fluid or Fixed Layout
Choose between preset widths of 750px, 950px, and 100% by giving a document-wrapping div an ID of doc, doc2, or doc3. These options cover most use cases, but it’s easy to define a custom fixed width.
The fluid 100% grid (doc3) is what I’ve been using almost exclusively since it was introduced in the last YUI released.
<body><div id="doc3"></div></body>- Source: /code/intricate-fluid-layouts/3.txt
All pages are centered within the viewport, and grow with font size. The 100% width page (doc3) preserves 10px of breathing room via left and right margins. If you prefer your content flush to the viewport, just add doc3 {margin:auto} to your CSS.
Regardless of what you choose in the other two steps, you can always toggle between these widths and behaviors by simply swapping the ID value. It’s really that simple.
Example: 100% fluid layout
Step 2: Choose a Template Preset
This is perhaps the most frequently omitted step (they’re all optional), but I use it nearly every time. In a source-order-independent way (good for accessibility and SEO), “Template Presets” provide commonly used template widths compatible with ad-unit dimension standards defined by the Interactive Advertising Bureau, an industry association.
Choose between the six Template Presets (.yui-t1 through .yui-t6) by setting the class value on the document-wrapping div established in Step 1. Most frequently I use yui-t3, which puts the narrow secondary block on the left and makes it 300px wide.
<body><div id="doc3" class="yui-t3"></div></body>- Source: /code/intricate-fluid-layouts/4.txt
The Template Presets control two “blocks” of content, which are defined by two divs, each with yui-b (“b” for “block”) class values. Template Presets describe the width and orientation of the secondary block; the main block will take up the rest of the space.
<body><div id="doc3" class="yui-t3"><div class="yui-b"></div><div class="yui-b"></div></div></body>- Source: /code/intricate-fluid-layouts/5.txt
Use a wrapping div with an ID of yui-main to structurally indicate which block is the main block. This wrapper—not the source order—identifies the main block.
<body><div id="doc3" class="yui-t3"><div id="yui-main"><div class="yui-b"></div></div><div class="yui-b"></div></div></body>- Source: /code/intricate-fluid-layouts/6.txt
Example: Main and secondary blocks sized and oriented with .yui-t3 Template Preset
Again, regardless of what values you choose in the other steps, you can always toggle between these Template Presets by toggling the class value of your document-wrapping div. It’s really that simple.
Step 3: Nest and Stack Grid Structures.
The bulk of the power of the system is in this third step. The key is that columns are built by parents telling children how to behave. By default, two children each consume half of their parent’s area. Put two units inside a grid structure, and they will sit side-by-side, and they will each take up half the space. Nest this structure and two columns become four. Stack them for rows of columns.
An Even Number of Columns
The default behavior creates two evenly-distributed columns. It’s easy. Define one parent grid with .yui-g (“g” for grid) and two child units with .yui-u (“u” for unit). The code looks like this:
<div class="yui-g"><div class="yui-u first"></div><div class="yui-u"></div></div>- Source: /code/intricate-fluid-layouts/7.txt
Be sure to indicate the “first“ unit because the :first-child pseudo-class selector isn’t supported across all A-grade browsers. It’s unfortunate we need to add this, but luckily it’s not out of place in the markup layer since it is structural information.
Example: Two evenly-distributed columns in the main content block
An Odd Number of Columns
The default system does not work for an odd number of columns without using the included “Special Grids” classes. To create three evenly distributed columns, use the “yui-gb“ Special Grid:
<div class="yui-gb"><div class="yui-u first"></div><div class="yui-u"></div><div class="yui-u"></div></div>- Source: /code/intricate-fluid-layouts/8.txt
Example: Three evenly distributed columns in the main content block
Uneven Column Distribution
Special Grids are also used for unevenly distributed column widths. For example, .yui-ge tells the first unit (column) to take up 75% of the parent’s space and the other unit to take just 25%.
<div class="yui-ge"><div class="yui-u first"></div><div class="yui-u"></div></div>- Source: /code/intricate-fluid-layouts/9.txt
Example: Two columns in the main content block split 75%-25%
Putting It All Together
Start with a full-width fluid page (div#doc3). Make the secondary block 180px wide on the right (div.yui-t4). Create three rows of columns: Three evenly distributed columns in the first row (div.yui-gb), two uneven columns (66%-33%) in the second row (div.yui-gc), and two evenly distributed columns in the thrid row.
<body><!-- choose fluid page and Template Preset --><div id="doc3" class="yui-t4"><!-- main content block --><div id="yui-main"><div class="yui-b"><!-- stacked grid structure, Special Grid "b" --><div class="yui-gb"><div class="yui-u first"></div><div class="yui-u"></div><div class="yui-u"></div></div><!-- stacked grid structure, Special Grid "c" --><div class="yui-gc"><div class="yui-u first"></div><div class="yui-u"></div></div><!-- stacked grid structure --><div class="yui-g"><div class="yui-u first"></div><div class="yui-u"></div></div></div></div><!-- secondary content block --><div class="yui-b"></div></div></body>- Source: /code/intricate-fluid-layouts/10.txt
Example: A complex layout.
Wasn’t that easy? Now that you know the three “levers” of YUI Grids CSS, you’ll be creating headache-free fluid layouts faster than you can say “Peace on Earth”.
Your comments
I’m just curious, does Yahoo use YUI Grids for any of its pages?
James – absolutely. Check out Yahoo! TV for a recent example.
Of course. Yahoo is actually very good at “eating it’s own dog food” . . . Specifically, as a Front End Engineer in the Media Group, I have worked with teams who have implemented the YUI Grids as well as the other libraries such as the connection manager, event, dom, animation and container libraries on Yahoo! Tech, Yahoo! Talent Show, Yahoo! News, the recently launched Yahoo! Food, and redesigned Yahoo! Health. Working with the folks on the platform team such as Nate has been an honor and pleasure. I am in awe of those guys almost every day!
@ James : Going forward, we also intend to use the grids quite a lot more than we currently do for more complex layouts, just as we very often use the YUI Javascript libraries to help standardise and normalise our sites.
I wonder, do the terms and conditions permit developers to change the id’s of certain elements in the CSS? The reason I ask is that it would really help add more semantic meaning to the document’s markup if you could use values of, “wrapper” instead of “doc3” and “subnav” instead of “yui-g.”
Great tutorial, Nate. I’ve been really impressed with the Yahoo grid setup (and the Javascript libraries, too) when I’ve played with it. It’s really nice to see it all laid out in a simple tutorial like this. Here’s hoping for widespread adoption!
@Christian: The entire YUI Library including Grids is available with a BSD license, perhaps the most open open-source license. Change or use the code in just about any way you like.
http://developer.yahoo.com/yui/#license
Though not an obligation in any way, let me invite you to share your experience and/or derivative work on our mailing list.
http://groups.yahoo.com/group/ydn-javascript/
@Christian: I know it’s the purist in us all but I’m not convinced it’s so important to change the doc3 ID – sure they could have been named after their widths or something but it doesn’t worry me personally. The added benefit of leaving as-is is when (if) Nate releases another version and you forgot to rename the IDs… By its very nature you can’t rename the classes that build the grid for you due to the dependencies.
About all I’ve done is add semantic IDs to some divs to act as a hook for the cascade and demonstrate to me the ‘important’ divisions on the page.
Thanks for the write-up Nate, this is actually clearer for me than the official page. I’ve only just released the redesign of my website and tonight I have already ported it to the YUI grids way on my dev server so I guess they’ll be another relaunch this weekend. The speed of putting layouts together is impressive.
OK, so I’ve had a quick play, and it does indeed seem to work pretty well. Nice and quick to put a layout together, nice and stable across all browsers I’ve looked at (and I don’t care much about the ones I haven’t, so long as it’s readable which I assume it is).
But it grates with me.
I mean come on, in the example given we have 5 levels of nested divs, and 14 divs to create 8 areas of content.
The classnames are also horrible and not exactly easily remembered for someone starting out with this. They’re also a little counter-intuitive – when I looked at the source before reading the article I assumed “doc3” was designating a 3-column layout for example.
Maybe I’m just worried that this is going to simplify one aspect of my job so much that anyone will be able to knock out a semantic, table-free layout with no experience? ;)
I think one of the biggest problems in my mind is that this example (whilst complex in layout) is actually very simple – there’s no backgrounds, padding, different margins, overlapping elements etc etc that a client will ask for. It works nicely for a basic example with no styling, but I feel it’d actually be a nightmare to work with once you start trying to put a design into it?
And the use of css “hacks” worries me as well, I see both the underscore and the * hack used in this file – have we not learnt anything since IE7 came out? Do yahoo not think conditional comments are the way to go? If they have an article on this issue somewhere I’d be interested to see it.
But the biggest problem has to be those nested divs. They make me shudder they do. I could make the same layout in considerably less code using a table, and it’d have guaranteed browser support, and would be very easily maintainable by someone who wanted to (for example) change the width of a column. What have we gained by going from a simple table to a complex div-soup?
A developer’s approach to design: Create a tight little package that solves many layout requests by flipping a switch here and there. On the one hand, it’s brilliant. It’s a swiss army knife, easily deployable, very useful. You want it? We got it – just dial the right combination.
On the other hand, I don’t know any html designer who wouldn’t take pride in creating his/her own html and css.
This is great for an IT group at a corporation to share with various departments that need their own special layouts. I see it being good for some one-man hosting company who offers ‘customized web design’ and can deploy these pretty quick. I don’t see it being so useful for independent designers, as they will want to do their own html and css. It’s not for non-designers like some guy throwing out an ‘about me’ page for his handyman businss, as who would want to learn “yui-u” and “yui-gb” and “doc3”?
Overall, it’s a powerfully little package.
I enjoyed the article and am finally convinced that I should start using the YUI grids. Plus, it was fun to first read the article and then realize you wrote it, Nate.
@Seb and anyone else concerned about the * and _ hacks might want to look at my CSS framework. It replaces old hacks with several HTTP requests although you can reduce that number by combining style sheets on the production server. It really just boils down to what works (or is acceptable) for any given project, hence the term framework I suppose.
It may be div-soup and involve more code than a table, but it linearises better than a nested tables-based design which dictates structure and position over a div layout that is structure put into position by CSS.
Thanks for the comments everybody. I’ve addressed them below:
@Seb:
I’ve heard the “divitis” charge before, but disagree strongly. The W3C says divs are “for adding structure to documents.” I take their guidance to heart: “this content is part of a column group” is correct usage. I’ve articulated that position on my blog and welcome discussion: http://nate.koechley.com/blog/2006/12/15/divitis_and_correct_div_usage/
+ Regarding class and ID names:
Names should not be based on appearance, but on meaning. For maximum extensibility, choose names that express semantic meaning (derived from the element’s content), and/or structural meaning (derived from the element’s role in the DOM’s tree). Good structural names include “footer” and “module”; good semantic names include “price” and “date”.
The common “doc” in doc, doc2, and doc3 is meaningful because this particular div is the document’s root node. It has no bond to a particular rendition or device. Similarily, “-b” (block), “-g” (grid), and “-u” (unit) classnames are meaningful yet neutral. The alternative, what-it-looks-like names such as “left” and “doc950px”, is contextually brittle (i.e., mobile) and temporally brittle (because things change). These are the same reasons professional consensus says class=“redButton” and class=“smallBoldVerdana” are undesirable.
+ Regarding the hacks for IE (*property) and IE7 (_property):
You’re right, you could pull those out into version-specific sheets exposed by conditional comments. I’ve included them in a single file in this case for two reasons. First, additional HTTP requests hurt performance. I value performance before validity, especially for infrastructure.
Second, the main argument against including CSS hacks — that they’re hard to manage — is moot in this case. CSS hacks are tedious, risky, and expensive to manage, and for those reasons I discourage intermingeling them in large codebases. But in this case the file is of encapsulated scope, is centralized, and has dedicated and permanent maintenance staff.
+ Does it work for demanding designs?
While everything’s breakable, the short answer is yes. It’s been used successfully on glossy sites with all the Web 2.0 trimmings: drop shadows, nested borders, rounded-corners, gradients… YUI Grids is a dependable skeleton. If you need more hooks, it’s rugged enough that you can embed your own markup and it won’t break.
@Karl:
Great to hear you were able to port your redesign so quickly! Very happy to hear it.
@Tony:
I definitely hear you when you say “you don’t know any HTML designer who wouldn’t take pride in creating” their own, It’s true, us geeks are a proud lot. But for my money, I don’t know many without something more interesting to do than reinvent the wheel. Efficient tools let us reach farther, but are never required.
+ What about those not interested in handcoding?
Dav Glass has created an outstanding wizard for building YUI Grids: http://blog.davglass.com/files/yui/grids/
Of course, your general argument applies to any tool, in any context, from “Ruby on Rails makes programming too easy!” to “painting with premixed colors is boring.”
@Michael: Thanks!
This may have been addressed already, but it’s late and i’m too tired to read through everything that’s been said in detail.
My issue with YUI Grids is that regardless of whether the class names used to hook the styles are meaningful, you’re doing your markup based on your styles rather than the other way round.
It may not be that much tag soup (though definitely more structural markup than necessary), but it seems to me that it’s a step backwards in terms of seperating style from content. It’s hard work producing markup that has no fluff, but I like to think that it’s worth it, even with all styles disabled every single character in the document source is adding to the meaningful information content of the page (I accept that it’s not always possible but it’s something we should aim for).
Don’t confuse this for blind designer or coder pride concerning my beautiful hand-crafted markup and style rules, i’m all in favour of using frameworks – I use YUI Fonts quite regularly and am quite interested in learning Django, Rails et al. But unless i’m missing some big part of YUI Grids, i can’t see how it’s the right idea.
I think your heart is in the right place, but the idea for the grids is all wrong. Like Andrew said, this is a step backwards.
In order to change the look of the site, I now have to touch the structural layer. So now presentation is being relegated back to the markup, which is just all kinds of bad.
Maybe I am missing something, though.
Well, most of the negative commentary seems to come from people who have yet to use the YUI stuff in actual production. The only problem I really ran into using the yui grids came down to inheritance and nesting, and thats really more a feature/problem of css then it is with the grids solution itself. (just try nesting gb or gc classes under g ones or vice versa, you’ll see).
But those problems aside, which are not really problems, since it forces you to rethink how you were planning your layout anyways, the grids are great. I’ve already used them on 3 different projects successfully and have to say I’m not going to be wasting my time going forward by trying to reinvent the wheel.
As to the hacks comments: conditional comments, separate css files, those are all great ideas, but those are perfect world solutions, not real world. If you find yourself having to hack ALOT, then someting is WRONG with your layout/markup, and you are creating those problems for yourself, not the browsers. In any large project I’ve worked on, by the time i’m done I have maybe 3 or 4 IE specific _ hacks in my markup (almost always related to the whole
has layoutproblem), and if the site is live and working fine, I’m TOTALLY ok with that, because that means I’m getting paid. ;)Commenting is closed for this article.
24 ways is an edgeofmyseat.com production.
Edited by Drew McLellan and Brian Suda. Possible only with the help of our wonderful authors.Grab our RSS feed or follow us on Twitter for updates. Hosted by Memset.