Tables existed in HTML for one reason: To display tabular data. But then border=”0″ made it possible for designers to have a grid upon which to lay out images and text. Still the most dominant means of designing visually rich Web sites, the use of tables is now actually interfering with building a better, more accessible, flexible, and functional Web. Find out where the problems rise from, and learn solutions to create transitional or completely table-less layout.
The problem with using tables:
1. Mixes presentational data in with your content.
- This makes the file sizes of your pages unnecessarily large, as users must download this presentational data for each page they visit.
- Bandwidth ain’t free.
2. This makes redesigns of existing sites and content, extremely labor intensive (and expensive).
3. It also makes it extremely hard (and expensive) to maintain visual consistency throughout a site.
4.Table-based pages are also much less accessible to users with disabilities and viewers using cell phones and PDAs to access the Web.
View this example below.
When we use tables for creating a layout, we lose the semantic nature of the page. If a page follows this semantic order:
Title of Page
Primary Navigation
Content
Secondary Navigation
Copyright Notice
But is marked up this way:
<table>
<tr>
<td colspan=”2″> Title </td>
</tr>
<tr>
<td width=”20%”>
Navigation
item
item
item
item
</td>
<td>
Primary content
—
Secondary Navigation
</td>
</tr>
<tr>
<td> </td>
<td>(c) 2002</td>
</tr>
</table>
All semantic meaning is lost. Speech or text-only browsers would not enjoy this layout very much. Switching to CSS can be the perfect way to turn that jumble into an accessible, easy to decipher page.
Rescue is at hand
Instead of nesting tables within tables and filling empty cells with spacer GIFs, we can use much simpler markup and CSS to lay out beautiful sites that are faster to load, easier to redesign, and more accessible to everyone.
The solution: CSS and structural markup
By using structural markup in our HTML documents and Cascading Style Sheets to lay out our pages, we can keep the actual content of our pages separated from the way they are presented.
This has several advantages over using tables.
Some argue that CSS posesses no replacement for table-based layout. However, it can be easy (if the browsers get their act together!) to create a simple layout.
If we take the previous structure:
Title of Page
Primary Navigation
Content
Secondary Navigation
Copyright Notice
and then implement the following HTML in the <body>:
<h1 id=”top”>Title</h1>
<ul id=”navigation”>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>
<div id=”main”>
The main content
<div id=”secondary”>
secondary navigation
</div>
</div>
<div id=”copy”>
© Foo, 2003
</div>
This is so much simpler, and you are able to see the clearly marked sections. Now to style this so it looks similar, or better, than the table-based version:
h1
{
border: 1px solid black;
}
#navigation
{
float: left;
width: 20%;
padding: 5px;
border: 1px solid black;
}
#copy
{
border: 1px solid black;
}
This creates a simple and easy to change layout. You will never need to modify every page, as you would with tables. Adding extra sections is very easy.
Bandwidth ain’t free
Using Web standards reduces the file sizes of your pages, as users no longer need to download presentational data with each page they visit. The Style sheets that control layout are cached by viewers’ browsers.
Reduced file size means faster loads and lower hosting costs.
All pages look like each other!
Using Web standards also makes it extremely easy to maintain visual consistency throughout a site. Since pages use the same CSS document for their layout, they are all formatted the same.
This strengthens your brand and makes your site more usable.
Write once, use anywhere, for everyone
Using Web standards makes our pages much more accessible to users with disabilities and to viewers using mobile phones and PDAs to access the Web.
Visitors using screen readers (as well as those with slow connections) do not have to wade through countless table cells and spacers to get at the actual content of our pages.
In other words, separating content from the way it is presented makes your content device-independent.
Improve your search engine ranking
Speaking of accessiblity, minimizing your markup and using header tags properly will also help improve your search engine ranking.
Reducing the ratio of code to content, using keywords in your header tags, and replacing header GIFs with actual text will all help your sites get better search engine results.
A pleasant enough looking table

A look beneath the surface
<table summary=”a unholy mess” border=”0″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td colspan=”9″ width=”553″ height=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
</tr>
<tr>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
<td width=”11″ height=”10″><img src=”images/spacer.gif” alt=”" height=”9″ width=”11″ /></td>
<td width=”150″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”150″ /></td>
<td width=”20″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”20″ /></td>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
<td width=”11″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”338″ /></td>
<td width=”20″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”20″ /></td>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
</tr>
<tr valign=”top”>
<td width=”11″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”150″>This could really be done much more simply.</td>
<td width=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”11″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″>Guess how much markup there is in this little table? 13.7k. There are 17 rows and 9 columns in this thing. And did I mention all of the spacer GIFs?</td>
<td width=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
</tr>
<tr>
<td width=”11″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”150″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”150″ /></td>
<td width=”20″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”11″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”338″ /></td>
<td width=”20″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
</tr>
<tr>
<td colspan=”9″ width=”553″ height=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
</tr>
<tr>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
<td width=”11″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”150″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”150″ /></td>
<td width=”20″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
<td width=”11″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”338″ /></td>
<td width=”20″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
</tr>
<tr valign=”top”>
<td width=”11″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”150″>There are way too many table cells and spacers in here.</td>
<td width=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”11″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″>And all of the dotted borders are done with a <code>background</code> attribute on table cells, which won’t validate.
<table summary=”list” width=”338″ border=”0″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td width=”10″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”10″ /></td>
<td width=”328″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”328″ /></td>
</tr>
<tr valign=”top”>
<td width=”10″>•</td>
<td width=”328″>A nested table? What for?</td>
</tr>
<tr>
<td width=”10″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”10″ /></td>
<td width=”328″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”328″ /></td>
</tr>
<tr valign=”top”>
<td width=”10″>•</td>
<td width=”328″>To make a bulleted list? You’re kidding, right?</td>
</tr>
</table>
</td>
<td width=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
</tr>
<tr>
<td width=”11″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”150″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”150″ /></td>
<td width=”20″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”11″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”338″ /></td>
<td width=”20″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
</tr>
<tr>
<td colspan=”9″ width=”553″ height=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
</tr>
<tr>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
<td width=”11″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”150″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”150″ /></td>
<td width=”20″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
<td width=”11″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”338″ /></td>
<td width=”20″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
</tr>
<tr valign=”top”>
<td width=”11″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”150″>This could all be done with 8 table cells and 4 CSS rules.</td>
<td width=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”11″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″>Seriously. 8 cells and 4 css rules, that’s all it takes.<table summary=”list” width=”338″ border=”0″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td width=”10″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”10″ /></td>
<td width=”328″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”328″ /></td>
</tr>
<tr valign=”top”>
<td width=”10″>•</td>
<td width=”328″>Oh no, another table masquerading as a bulleted list.</td>
</tr>
<tr>
<td width=”10″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”10″ /></td>
<td width=”328″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”328″ /></td>
</tr>
<tr valign=”top”>
<td width=”10″>•</td>
<td width=”328″>Just mark up your bulleted lists as bulleted lists and let CSS do the rest.</td>
</tr>
</table>
</td>
<td width=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
</tr>
<tr>
<td width=”11″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”150″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”150″ /></td>
<td width=”20″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”11″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”338″ /></td>
<td width=”20″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
</tr>
<tr>
<td colspan=”9″ width=”553″ height=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
</tr>
<tr>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
<td width=”11″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”150″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”150″ /></td>
<td width=”20″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
<td width=”11″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”338″ /></td>
<td width=”20″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td rowspan=”3″ width=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
</tr>
<tr valign=”top”>
<td width=”11″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”150″>You need a rule for <table>, one for <td>, one for <ul> and one for <li>.</td>
<td width=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”11″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″>That’s it. Once you have those you’re golden.<table summary=”list” width=”338″ border=”0″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td width=”10″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”10″ /></td>
<td width=”328″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”328″ /></td>
</tr>
<tr valign=”top”>
<td width=”10″>•</td>
<td width=”328″>That’s better than using 8 more table cells to make a fake bulleted list, which ends up being much less accessible.</td>
</tr>
<tr>
<td width=”10″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”10″ /></td>
<td width=”328″ height=”10″><img src=”images/spacer.gif” alt=”" height=”10″ width=”328″ /></td>
</tr>
<tr valign=”top”>
<td width=”10″>•</td>
<td width=”328″>Excellent! The last fake bullet.</td>
</tr>
</table>
</td>
<td width=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
</tr>
<tr>
<td width=”11″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”150″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”150″ /></td>
<td width=”20″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”11″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
<td width=”338″ height=”20″> </td>
<td width=”20″ height=”20″><img src=”images/spacer.gif” alt=”" height=”10″ width=”11″ /></td>
</tr>
<tr>
<td colspan=”9″ width=”553″ height=”1″ background=”images/1dot.gif”><img src=”images/spacer.gif” alt=”" height=”1″ width=”1″ /></td>
</tr>
</table>
Recapping transitional designs
Use margin and padding instead of extra cells and spacer GIFs.
Use link and @import styles. The first for old browsers, the second for modern browsers.
<link href=”basic.css” rel=”stylesheet” type=”text/css”>
<style type=”text/css” media=”screen”><!–@import url(modern.css) screen;–></style>
CSS layouts: the future is here
The browsers that the vast majority of viewers are using today have good CSS support. They all have their quirks, but once you get used to them, you can work around them.
Coding CSS is easy. Even for a guy like me who thinks that most JavaScript looks like swear words.
if(links[x].length > 0);{
for (y=0; y<links[x].length; y++) {
Every CSS rule has a selector and a declaration. The declaration is made up of a property and a value. Properties that sound like they should be 2 words are hyphenated.
body {margin:0; padding:0}
.related {float:right; width: 15em; margin-left:1em; margin-bottom: 1em; color:blue}
#footer {color: gray; font-size: 0.6em; line-height: 1.2em; background-color: white; margin: 0}
Structural markup: code what you mean, mean what you code
While writing the actual CSS is simple, using CSS to do your layouts requires a slightly different way of thinking than most of us are probably used to.
Rather than thinking about things like “this goes here and this goes here” while we are working on a page or a layout, we need to think about the kinds of information in our page and the structure of that information.
We give the most important headline an <h1> tag; subheads get marked up with <h2> tags, etc.; and paragraphs are paragraphs.
This is what is known as “structural” or “semantic” markup.
Instead of putting your content inside of tables and table cells, wrap it in div elements. Give your div elements an id or a class that is descriptive of their content and/or function, rather than their appearance.
Avoid <b> and <br> markup
Think about why you want something to appear a certain way; what does it mean? Your markup can and should convey meaning, even to someone who cannot see your page. Semantic markup makes our pages more accessible to everyone, including search engines.
When you italize something, is that because you want to emphasize it, <em>.
If something is bold, it should probably be marked up as <strong>.
If you want a linebreak after something, chances are it should be marked up as a header element. If it’s not a header, is it part of a class that occurs throughout your site? If that’s the case then use CSS instead of <br>.
.foo {display:block}
What are nav bars?
Think about it: your navigation is actually an unordered list of links.
Mark them up inside <ul> tags.
* link1
* link2
* link3
* link4
* link5
Horizontal Nav bars
We can use CSS to control how these lists are displayed on our pages.
By using display:inline we can create horizontal nav bars.
Breaking down your pages
Once you have a grasp on the types of content in your site, it’s time to analyze your existing pages for logical divisions of content.
* Main navigation
* Subnavigation
* Headers and footers
* Content
* Related information
* Other
Analyze your table structure for nested tables and empty spacer and border cells. (We want to replace these with div tags or with a much simpler table structure.)
Replace presentational tags with structural markup
You can use find and replace (and regular expressions), but the easiest way to do it might be to view your existing page in a browser and copy and paste the text from there into your HTML editor.
Think about the structure of your document! Merely replacing <b> tags with <strong> tags is not enough.
What is the most important header? Mark it up with an <h1> tag. Mark your subheads with <h2> tags and so on. Mark up paragraphs with <p> tags. Mark up your navigation as unordered lists.
Choose a DOCTYPE and use it. (We recommend XHTML transitional, unless you’re hard core, in which case, go for it and use XHTML strict.)
Divide your page into logical divs
Put your main navigation into a div with an id of mainnav; put your subnav inside a div with an id or class of subnav, put your footer in a <div id=”footer”>, and wrap your content inside a <div id=”content”>.
It doesn’t look like much now, but once you start adding rules to your style sheets, things will get better quickly.
It’s time to start writing your CSS
At the begining, give each div a border. For example, div {border: 1px solid #000000; padding: 10px} This will help you see where they begin and end, and also whether or not you have any nesting going on.
Write your CSS for element selectors first (<html>, <body>, <p>, <h1>, <h2>, <ul>, <li>, etc.)
Use contextual or descendant selectors as much as possible. This will keep your markup much cleaner. For example, #subnav li {border: 1px solid #000000; padding: 10px; display: inline} will only affect list items that occur within your subnav div.
Examples of sites that are laid out with CSS
* CSS Zen Garden
* Adobe Studio
* ESPN
Concluding for Now..
I can’t cover everything you need to know about designing with CSS in one post, but you can read books that can help you with using Web standards to make your pages leaner, cleaner, and faster.