From Table Hacks to CSS Layout: A Web Designer’s Journey

This is a journey from six years of conventional web design practice to the way we’ll build sites in the future. Only it’s not set in the future. You’re soaking in it.

Article Continues Below

From the beginning, we’ve done whatever we had to do to make our sites work in every browser. In the world of non-standard HTML Design, we bolt every word, every image into place by manipulating table cells.

And we solve problems by replacing them with new ones. Netscape 4 ignores the CSS {margin: 0;} declaration? Extend the BODY tag with the Four Horsemen of Non-Validation: LEFTMARGIN, TOPMARGIN, MARGINWIDTH, MARGINHEIGHT. IE4 doesn’t fully support the CSS border property? Fake it by wrapping a black HTML table around your white one. Sure, it shouldn’t work, but it does, and this site was due yesterday. Build, test, rebuild.


That’s how sites got built in 1995, and it’s how they’re built today. It’s a messy, confusing business whose lack of logic created a market for visual web editors like Dreamweaver, GoLive, and FrontPage. Meanwhile, we hand-coders often pride ourselves, not on the quality of our work but instead on our arcane knowledge of which non-standard tag or snippet of JavaScript “fixes” which rendering problem in which stupid browser.

We complain about the WYSIWYG editors, but we write the same kind of code ourselves. When we don’t know how to do something, instead of consulting the W3C or ECMA standards, we share hacks on mailing lists or across the cubicle. And when a browser comes out that actually supports standards, we complain about the way it breaks our HTML workarounds and browser-specific “DHTML.”

This is a mighty stupid way to work. But it gets worse when we have to redesign. Unless we work with proprietary publishing systems (which have problems of their own), all that old content riddled with FONT tags and stuck inside table cells has to be poured into our new templates by hand – one page, one table cell, at a time.


We all know the future is about web standards. And web standards are about the separation of style from content – presentation from structure – design from data.

We all know that there are browsers on the market right now that more or less completely support these web standards. IE5, Netscape 6, and Opera 5 offer CSS, HTML, and JavaScript/ECMAScript compliance solid enough to let us discard the clumsy methods of the past, and liberate the web from the bondage of HTML Design.

We also know that millions of people view the web through 4.0 and older browsers. And this knowledge prevents us from crossing the line and implementing tomorrow’s web methods right now.

I crossed the line.


Horror movies teach us never to enter a dark room alone. Before embarking on a completely new way of designing websites, I found stalwart companions to accompany me into the darker corners.

Two of these brave souls were CSS experts who had helped create the standards in the first place; as they choose to remain anonymous, I will refer to them as Anonymous Donors A and B.

Later in the quest, ALA’s David Eisenberg joined our small band of adventurers, running cross-platform tests and deliberately altering our emerging style sheet to verify various levels of CSS compliance on a browser-by-browser basis.


If you think about it, there are two ways to create standards-compliant sites: one that complies with the letter of web standards, and the other that complies with their spirit.

THE LETTER#section6

The safe, conservative way follows the letter of web standards by avoiding validation errors. But it falls short of the spirit of web standards by continuing to bind style to content in chains of iron.

For instance, the WaSP’s site has always been standards-compliant, and has always used CSS to control its typography. But the layout is done with HTML tables so the site will work in any desktop browser.

The benefit: what I just said – it works in any browser. The drawbacks:

  1. Changing the design means hand-editing thousands of individual table cell colors, heights, and widths, or crafting new table layouts – a time-consuming and costly process.
  2. These HTML layout techniques are meaningless to non-traditional browsers and are considered harmful by the W3C, even if the pages validate.
  3. These traditional techniques make pages less accessible to people and devices.

THE SPIRIT#section7

And then there is the second way, the Holy Grail of web standards: separating style from content, using structural markup for data, and CSS for all aspects of visual layout control. I’d been using CSS since 1997, but had never cranked the volume to 11. Now, with help from my friends, I would do just that.


The traditional ALA layout was a maze of intricately nested HTML table cells. When updating it in the past, even I couldn’t follow the purpose of some of those complexly interdependent column spans and row spans – and I had created the damn thing.

<!-- Dress left -->
 <table border="0" cellpadding="0" 
<!-- Your variable left margin -->
 <tr valign="top"><td width="15%" 
 bgcolor="#ffffcc"> </td>
 <td width="75%" bgcolor="#ffffcc" 
<!-- Your actual content -->

Could we have that in English, please? I ached like a boy on Prom Night at the thought of replacing 10,000 maniacal table cells with two or three clean, simple HTML DIVs.


This is as good a place as any to raise the issue of rethinking your layout as you move from HTML Design to CSS – because that’s exactly what I did at this point. The traditional HTML layout was a three-paneled liquid affair; it squashed and stretched to accommodate your monitor. I wanted to recreate that liquidity in CSS, but I wasn’t keen on reproducing all three panels.

[The traditional ALA brand panel.]


I decided that the top panel – the familiar orange brand panel – was unnecessary, and probably always had been. From now on, branding could be handled in the content panel itself.

Frankly, creating a three-paneled layout in CSS also looked close to impossible to achieve, though such capabilities are planned for CSS-3. {Actually, a three-panel layout is relatively easy to achieve in CSS, as seen in these examples by Porter Glendinning and your humble author. But at the time of the first ALA CSS redesign, the problem appeared daunting. – Ed.}

It is easy to do absolute positioning in CSS, and that’s the part of the standard that most web designers jump on. But liquid design can’t be achieved with pixel-perfect positioning. For a site to squash and stretch, the design elements must be sized and positioned in relative, not absolute, terms. This kind of thing is easy to do in HTML tables, and it’s another reason tables have hung on as long as they have. How could it be done with style sheets?


My first thought, the obvious one, was to create two HTML DIVs: one for content, the other for the greenish menu area at right. And my first attempt nearly did the job.  A “content” DIV is declared this way in the embedded style sheet:

.content {width: 75%; padding-left: 10%; padding-right: 10px; padding-top: 10px;}

The content DIV takes up 75% of the width of the page, and has a little padding to create white space between its edges and filling. Meanwhile, a “menu” DIV is assigned to take up the remaining 25% of the width of the page (and 100% of its height):

.menu {position: absolute; left: 75%; top: 0px; height: 100%; width: 25%; margin: 0; padding-left: 15px; padding-right: 10px; padding-top: 10px; background-color: #cc0; background-image: url(backgrounds/striperight.gif); font: 10px/14px geneva, arial, helvetica, sans-serif;  color: black; }

In IE5/Windows, this worked as expected. But in browsers considered to be even more standards-compliant than IE5/Win, I got horizontal and vertical scrollbars. (You’ll see them in IE5/Mac, Netscape 6, and Opera 5.)

What was up with that? 100% of a page’s height was 100%, wasn’t it? 75% plus 25% still equalled 100%, didn’t it? Why were these browsers messing up so badly?

The answer, of course, is that they weren’t. I was – because I didn’t understand the CSS box model correctly (and neither did IE5/Win).


Memorize this: In the CSS box model, padding and borders are added to the overall size.

A box 300 pixels wide, with 20 pixels of inner padding, is 300 pixels wide in IE/Windows. That seems right, but it’s wrong according to the CSS1 spec.
A box 300 pixels wide, with 20 pixels of inner padding on each side, is 340 pixels wide in CSS-compliant browsers (300 + 20 pixels on the left + 20 pixels on the right). That’s because padding, even though it occurs on the INSIDE of the box, is added to the overall width per the CSS1 spec.

Many web designers who wrestle with CSS have asked why IE and Netscape 6 handle DIVs differently. The answer is, on the Macintosh platform, they don’t. IE5/Mac and Netscape 6 (like Opera 5) get the CSS box model right. IE5/Win gets it wrong. In Windows, IE and Netscape differ because Netscape gets the box model right. IE6, I can only dream, will get it right as well.

{Ed: Since this article was initially written and designed, the IE6 beta has been released to the public. It does indeed get the CSS box model right. This article was rewritten and redesigned on 7 April 2001 to accommodate these changes in the browser kingdom.}


This box-model brouhaha also explains why IE5 and Netscape 6 handle border properties differently. A 10 pixel border is correctly added to the outside of the DIV, or paragraph, or whatever block-level element on which it occurs. If you fill the entire screen with an image, and add a 10 pixel border to that image, you’ll get scrollbars in a truly CSS-compliant browser, because your overall image is now 20 pixels too big for the screen. In IE5/Win? No scrollbars. The way IE5/Win works seems preferable in many ways, but it’s wrong.

IE5/Mac emulates non-standard IE5/Windows behavior in Quirks mode, but delivers accurate standards compliance in Strict mode. You trigger Quirks mode by leaving out the DOCTYPE or creating a DOCTYPE with no W3C URL:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

You trigger Strict mode by beginning your page with a DOCTYPE that includes the relevant W3C URL:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 

The Gecko browsers (Mozilla, Netscape 6.x) follow IE5/Mac’s lead, as does the IE6 beta [now IE6 — ed.]. In all these browsers, you can use DOCTYPES to control whether you want your site to comply with standards as written, or to emulate the behavior of older, less compliant browsers.


Now you can see why my first iteration of the ALA redesign was saddled with scrollbars. Add my padding and margins to the percentages I was using. 75% plus 25% equals 100%. Plus padding of 10% and 10 pixels for the content DIV. Plus an additional 25 pixels for the menu DIV. It’s a wonder it worked at all.

How was I going to work around the intractable exactitude of numbers and rules? I couldn’t exactly write this in my style sheet:


If I had been using absolute widths, I’d just specify those widths and let the page be as wide as it needed to be. But that would result in a static, print-like layout that might be too wide for some people’s monitors, too narrow for other folks’. I was creating a liquid layout. If I just started fudging my numbers, they would never add up. It was clearly impossible to mix percentages and padding in this way without creating absurdly unworkable totals: 103%? 104.25%? It would vary for each monitor, but it would always be wrong.

At this point Anonymous Donor A solved the box model problem by thinking outside the box.

FLOATIN’ & FUDGIN’#section15

Instead of conceiving of the ALA layout as an off-white content page interrupted by a right-aligned menu area, Anonymous Donor A conceived of it as a green page interrupted by a naturally left-aligned content area. He then employed the little-used CSS “float” property to float the content to the desired width:

#content   {
 float: left;
    width:  67%; 
    padding: 45px 10% 100px 15%; 
    margin: 0 15px 0 0;
    border-right: 2px dotted black;
    border-bottom: 2px dotted black;

Notice that the gif background image used in my first draft layout has been replaced by the CSS border property (2px dotted black). Notice also that the percentage has shrunk from 75% to 67%.

Actually, we determined that the ideal width was even narrower than that. In monitor settings below 800 x 600, a menu area of 25% was insufficiently wide. As a result, menu items would slip down to the bottom of the page (screenshot). The ideal width for the content area turned out to be 52%. Remember, that’s 52% before the padding and margins are added. You may want to go get drunk for a while, then come back and try this again.


  1. Why hadn’t this problem cropped up in the old ALA table-based layouts? Because table-based layouts are sloppy to begin with. With a table-based layout, if your menu area is too narrow, the browser simply fudges the proportions. CSS-compliant browsers will not fudge proportions to save you from your own stupidity.
  2. If the ideal width was actually 52%, then why is the content DIV declared at a width of 67%? Simple: 67% is a bogus value to fool Windows IE5 into displaying the actual value more or less correctly.

Remember, IE5/Win gets the box model wrong by absorbing padding and margins without adjusting the overall width. 67% is approximately what 52% looks like after you add padding and margins.

I’m describing in a paragraph what took 14 hours to figure out. You may want to sniff glue for a while, then reread this when you get out of rehab.


From what I’ve said so far, you might think my anonymous cohorts and I decided to set up the CSS layout so it would only work correctly in a less standards- compliant (but more widely used) browser, IE5/Win. Not so.

Anonymous Donor A used a CSS2 declaration to set the correct width:

body>#content {
 width: 52%; 
    padding: 35px 5% 100px 10%;

If body># looks like a typo, it’s not; it’s a CSS2 selector. IE5/Mac, Netscape 6, and Opera 5 understand CSS2 syntax. IE5/Windows doesn’t, so it skips it. IE5/Win follows the rule it understands: the bogus 67% width. More conformant browsers follow the CSS rule of greater specificity. What’s that, you ask?


A global style sheet declares that all text in the <body> of a web page should be 1em Arial. But a paragraph is declared to be .8em Verdana.  You’ve styled the paragraph directly, so the paragraph is styled the way you’ve indicated,
rather than inheriting from the <body>.

If you then create a special paragraph class – say, “legalese” – and declare that “legalese” is always 10px tall, the greater specificity of <p class=“legalese”> will give you that 10px fine print loved by legal departments everywhere.

The more specific rule wins out over the less-specific rule.

In the wacky world of CSS, a content div that appears in the <body> is considered more specific than a content div declared on its own, even though they mean the same thing. If IE5/Win could read CSS2 syntax, it would do as the other browsers do, and this trick wouldn’t work.


So now we had a liquid layout designed entirely in lean, clean CSS. A layout that would display properly in any decently CSS-compliant browser, but was far too complex for a 4.0 browser.

That’s where the WaSP’s Browser Upgrade initiative kicked in. And where Anonymous Donor B had the brilliant idea of using iframes to cue users of 4.0 and older browsers to the desirability of upgrading. Unfortunately, iframes are not supported in later versions of XHTML, so we later replaced the iframes with OBJECT tags.

Unfortunately, text inside invisible OBJECT tags showed up in standards-compliant (but limited) browsers and devices such as Lynx and Palm Pilots™. So we added JavaScript to the OBJECT tags to cloak their content from those browsers and devices.

Unfortunately, adding JavaScript to the OBJECT tags caused IE5+/Windows to hide the TITLE of web pages, and also caused IE5+/Windows to report bogus security alerts in some cases, depending on user security settings.

Eventually Anonymous Donor A crafted fiendishly tricky (but absolutely standards-compliant) workarounds that would not louse up any browser. But by that point, we had surrendered. We’re now wrapping our “upgrade” message in a simple <P> tag, and using CSS to hide that tag:

<p class=“ahem”>

This site will work and look better in a browser that supports web standards, but it is accessible to any browser or Internet device.

How and why this works is explained on the WaSP’s developer tips page.


There was one more decision to make: whether or not to let 4.0 browser users see the woeful way their browser botched the new style sheet. We decided to shield them from it.

There are many ways to do that, foremost among them JavaScript browser detection or server-side technologies. We decided to use HTML instead. Rather than link to our style sheet the conventional way …

<link rel=StyleSheet href="/css/style.css" 
type="text/css" media=screen>

… we linked to it thusly:

<style type="text/css" media="all">
@import "/nucss.css";

5.0+ browsers understand that method. 4.0 browsers don’t. Kids, try this at home.

By using the @import method with double quotes, you protect 4.0 browsers from themselves, and have the freedom to use CSS as it was always meant to be used. This is another way of saying you finally have the freedom to use a web standard per spec, instead of kludging and compromising it at the gate.

And for people who make websites, that is nothing short of revolutionary.


Late in the game, we discovered that IE4.5/Macintosh understands the @import method of linking to a style sheet. It also, incredibly, gets the box model right. But it does not understand CSS2 selectors.

So IE4.5/Mac displays the contentdeclaration as written, per CSS1 spec. Unfortunately, the contentdeclaration, as you may remember from reading it a few paragraphs ago, was written using bogus values to trick IE5.5/Windows into displaying the layout correctly. IE4.5 therefore does a perfect job of displaying the wrong declaration, and in that browser the layout will be more than a bit off.

And now the final kink. After ALA was redesigned using the methods described in this article, the IE6 beta for Windows was released to the public. Like IE5/Mac, it supports DOCTYPE switching. Like IE5/Mac, Opera 5, and the Gecko browsers, it gets the CSS box model right. Unlike those browsers (but just like IE4.5/Mac), it does not recognize CSS2 selectors.

So, just like IE4.5/Mac, the IE6 beta does a perfect job of displaying the wrong declaration. The browser is right but the layout is wrong.

Fortunately, we had solved this problem by ALA Issue No. 100, which uses a simpler style sheet and a wrapper DIV to hold all the pieces together in any CSS-compliant browser.


During the first week of April, web designers who use CSS, experts who’ve helped create the CSS recommendations, and a standards-oriented browser developer, all participated in an informal group discussion about the best ways to create CSS layouts that compensate for browser differences.

Much of this has been summarized by participant Eric Costello, and many of us netted out on using a CSS box model hack created by Tantek Çelik, development lead for the Tasman rendering engine, and contributor to CSS2 and CSS-3. It looks scarier and more complex than it really is.

The CSS techniques used at ALA since Issue 100 are based on a different approach, and they function well in IE6 beta, IE5/Win, IE5.5/Win, IE5/Mac, Mozilla, Konqueror, Netscape 6, and Opera 5.


Replacing HTML table hack layouts with valid CSS is good for web users, designers, and the medium’s stability and growth. The article you’ve just read, endless though it may seem, barely scratches the surface. Since this article was first written, several fine resources have sprung up, including:

  1. BlueRobot’s CSS Layout Reservoir and CSS Centering mini-tutorials #1 and #2
  2. Glish’s CSS Layout Techniques
  3. Owen Briggs’s amazing Little Boxes visual layouts page, and the Box Lesson Problem & Workaround Set, which addresses bugs in various browsers.


The separation of style from content is at ALA today, but tomorrow, or the day after, it will be at all sites. Far from seeming revolutionary, difficult, dangerous, or non-user-friendly, it will simply be the way the medium functions. It is, after all, the way the web was always meant to work.

Those who think of the web primarily in terms of graphic design will need to enlarge their views, but they won’t lose their talent or their vision in doing so, and they will gain tremendously in control and flexibility.

Maybe you will join some of us as we try to roll the rock uphill a little faster than typical user upgrade patterns dictate. Maybe you’ll sit back to see how the whole thing shakes out. But whether you choose an activist role or a non-participatory one, now would be a good time to start learning how these standards really work, and the power they can bring to your sites.

Even if you choose to keep your CSS and other standards-based experiments offline, or share them only with a select few, the time to experiment and learn is now. Because very, very soon the whole web will work this way. And you’ll want to be part of it – because ultimately it is a better, less-frustrating, more powerful way to build websites.

Of course, if you choose not to learn about CSS and other web standards, MacDonald’s restaurants are said to have an excellent management training program.

We will see some of you at the barricades, and the rest another mile up the road.

No Comments

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA