Replacing Tables with CSS for Page Layout
Introduction
This is one in the occasional series about design and layout, this time covering the replacement of tables with CSS. I must confess that I resisted doing this for a long time and now with the zeal of a religious convert I regret this. There were all the normal excuses about backward compatibility and older browsers etc, but with newer non-Microsoft browsers around it's time to ditch the old ways of coding and upgrade the old browsers. So I converted my own site and these Virtual Workshops to table-less layout and I'll show you how it was done (as with all the VWs this is my way, but you may find a different method which suits you better.)
What is CSS?
I have written a brief guide to CSS that I recommend you read even if you are familiar with CSS.
What's Good About CSS?
Accessibility - big issue especially within education / government.
Less Code - In recent years I've gone off the idea of editing pages with a complex layout by hand, simply because it became far to abstract (i.e. which nested table I am editing). Using CSS brings a simplicity back to page code that I haven't seen since I started coding HTML back in 1996.
Ability to change the Appearance quickly - Although something like Dreamweaver templates or cleverly used SSI would allow you to do the same, changing the appearance is as simple as writing a different style sheet. For example, look at the alltheweb search engine site. You can 'Skin' the site changing its appearance to one you prefer. This is going to be an increasingly used feature, although whether it is a fad or here to stay only time will tell. Personally I think this is useful in terms of changing the way we think when making a page with a wider adoption of XML /XLST around the corner as it separates the design from the content.
Getting Started.
For the purposes of this Virtual Workshop, we'll use the design that we looked at in the Visual Design Tips Virtual Workshop. In that workshop we looked at constructing a page with a table layout as follows.

This is a layout of sections within cells (Links to Sections, Links to Pages, Main Page Content) with a LOGO section above, a Copyright Section below and the last section (Links Insert) in another, nested, table. We are going to put all these sections into HTML then use Style Sheets to control where they are displayed. Using this technique is rather like creating a series of nested boxes, instead of having cells and nested tables.
Level One
This defines the sections within the BODY area of the page (the red border).
The Blue boxes here represent sections:
- The LOGO Area.
- Links to the Sections within the Website.
- Main Page Info (Where the Content and Links to Pages are).
- The Copyright information area.
Level Two
The Next Level is nested within the 'Main Page Info' section defined in Level One.

The green boxes represent the two sections:
- Links to Pages - where the pages relevant to this section are.
- Main Page Content.
Level Three
The Third Level of nesting these sections happens within the Main Page Content section, into which we will add the Links Insert.

Setting Up the Level One Sections
We will use the 'Div' tag to define our sections as this will allow us to apply styles (stored in a linked 'tableless.css' file) to these sections later. We well also add the other HTML code for each section (for reasons of brevity I have left out the javascript used for rollovers).
<html> <head> <title>Example Design</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <link rel="stylesheet" href="tableless.css" type="text/css"> </head> <body> <div id="logo"> <img src="images/logo.gif" width="400" height="65" alt="Keith Brown Logo" /> </div> <div id="sect_nav"> <img src="images/iti_n.gif" width="96" height="20" name="iti" border="0"> <img src="images/web_n.gif" width="92" height="20" name="web" border="0"> <img src="images/dde_n.gif" width="92" height="20" name="dde" border="0"> <img src="images/own_n.gif" width="100" height="20" name="own" border="0"> </div> <div id="main"> </div> <div id="copyright"> <p>Owned By: <a href="mailto:keith.brown@blueyonder.co.uk">Keith Brown</a> last updated: <!--#config timefmt="%d %b %y" --><!--#echo var="last_modified" --></p> </div> </body> </html>
This results in this incomplete appearance. While the Logo area is OK (because it is using an existing element) the Section Navigation and Copyright Areas are not.
NOTE: To line up the images without a gap I've split the markup across lines in the 'real' examples.
The Level One CSS
To remedy this we have to add some styles to new a 'tableless.css' style sheet (referenced in the html above) to control the appearance.
NOTE: I'm using a base font size of 10px as it is easier to set the proportional font sizes in the CSS later. E.g. to set a font of 19px, you set it to 190%.
body {
width: 720px;
margin: 0px;
padding: 0px; // this is a concession to opera 7
// which has margin 0,
// but some padding by default.
font-size: 10px;
}
/* Sets Width to Maximum allowed */
div#logo {
width: 720px;
height: 65px;
}
/* Sets Height and width, aligns images right
and Sets the Background Colour */
div#sect_nav {
width: 720px;
height: 20px;
background: rgb(0,102,0);
text-align: right;
}
/* Sets Width to Maximum allowed */
div#main {
width: 720px;
background: rgb(51,204,153);
}
/* Set's Style for the Copyright Paragrh text */
div#copyright p {
font-family: Tahoma, sans-serif;
font-size: 90%;
color: div#336633;
margin-left: 5px;
font-weight: bold;
clear: both;
}
This Should begin to put the elements back into place.
NOTE: I have defined the 'main' area as having a green background (might not be visible until there is some content added depending on your browser) this is the base colour for the middle section which the Level 2 nested boxes will overwrite
Setting Up the Level Two Sections
In the HTML add another two DIV tags for the 'Links to Pages' and 'Main Page Content' sections within our exiting 'main' section.
<div id="main"> <div id="mainpage"> <h1>Heading One</h1> <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt t laoreet dolore magna aliquam erat v olutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam.</p>
<h2>Heading Two</h2> <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt t laoreet dolore magna aliquam erat v olutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis.</p>
</div> <div id="pagelinks"> <p>Navigation <ul> <li><a href="#">Link One</a></li> <li><a href="#">Link Two</a></a></li> <li><a href="#">Link Three</a></a></li> <li><a href="#">Link Four</a></a></li> </ul> </p> </div> </div>
We place the links after the main content for accessabilty reasons so the content is read first by speach browsers. This creates a page that looks like this. Which I'm sure you agree is pretty awful so time to add the CSS again.
The Level Two CSS
There are a couple of things to note before beginning.
- We can begin to see the usefulness of contextual selectors, where we can define a slightly different <p> tag for every section (e.g. div#copyright p, div#pagelinks p and div#mainpage p).
- We are going to use a contextual <ul> for our links.
- We will use position: absolute to make the pagelinks section display to the left of the mainpage section.
/* Defines the pagelink width and location */
div#pagelinks {
position: absolute;
left: 0px;
top: 90px;
width: 120px;
background: rgb(51,204,153);
}
/* Defines the Links */
div#pagelinks p {
font-family: Arial, Helvetica, sans-serif;
font-size: 130%;
font-weight: bold;
margin-left: 5px;
}
div#pagelinks ul {
font-family: Arial, Helvetica, sans-serif;
font-size: 100%;
color: rgb(255,255,255);
text-decoration: none;
text-transform: uppercase;
font-weight: lighter;
list-style-type: square;
margin-top: -5px;
line-height: 110%;
}
div#pagelinks ul a:link {
color: rgb(255,255,255);
text-decoration: none
}
div#pagelinks ul a:visited {
color: rgb(255,255,255);
text-decoration: none
}
div#pagelinks ul a:active {
color: rgb(255,255,153);
text-decoration: none
}
div#pagelinks ul a:hover {
color: rgb(0,102,0);
text-decoration: none
}
/* Defines the pagelink width and location */
div#mainpage {
width: 600px;
margin-left: 120px;
background: rgb(255,255,255);
}
/* Defines the Styles for this Section */
div#mainpage p {
font-family: Arial, Helvetica, sans-serif;
font-size: 130%;
line-height: 150%;
margin-left: 10px
}
div#mainpage h1 {
font-family: Tahoma, sans-serif;
font-size: 240%;
color: rgb(0,102,0);
margin-left: 5px
}
div#mainpage h2 {
font-family: Tahoma, sans-serif;
font-size: 160%;
color: rgb(0,102,0);
margin-left: 5px
}
This should have resulted in a page that is beginning to look like the original. Next we have to add our Links Insert
Setting Up the Level Three Section
Fairly simple stuff again. At the top our mainpage section add the new 'insert' section and content.
<div id="mainpage">
<div id="insert">
<h1>Lorem ipsum</h1>
<a href="http://tinyurl.com/378ja">What it means</a><br />
<a href="http://www.microbion.co.uk/web/dwext.htm">DW Extension</a><br />
<a href="http://www.websitetips.com/info/html/ipsum.txt">Text File</a><br />
<a href="http://www.lipsum.com/">Generator</a><br />
</div>
Once more as this has no style attached to it the page looks incorrect. Notice though that because we haven't written a <h1> style for the section yet it inherits the style from the parent section.
The Level Three CSS
There are another couple of things to note when we are applying styles in this section.
- We are going to use a display: block property to make the H1 text fill the whole section.
- We are going to use the 'A' tag on its own (without being in context of another style) to control the appearance of the links.
/* Set's the width and position */
div#insert {
width: 120;
float: right;
text-align: right;
}
/* Defines the title */
div#insert h1 {
display: block;
font-family: Arial, Helvetica, sans-serif;
background: rgb(0,102,0);
font-size: 170%;
color: rgb(255,255,255);
}
/* Defines the links */
div#insert a {
font-family: Arial, Helvetica, sans-serif;
font-size: 10px;
color: rgb(0,102,0);
text-decoration: none;
text-transform: uppercase;
font-weight: lighter;
text-align: right;
}
div#insert a:link {
color: rgb(0,102,0);
text-decoration: none
}
div#insert a:visited {
color: rgb(0,102,0);
text-decoration: none
}
div#insert a:active {
color: rgb(0,102,0);
text-decoration: none
}
div#insert a:hover {
color: rgb(51,204,153);
text-decoration: none
}
And lo and behold we have the same appearance as with the table layout. We have a smaller HTML file, the code is easier to read and because we have stored the styles in an external style sheet we can easily update the style of the site.
A Few Bits of Fun
Now that we have successfully converted the tables to CSS I want to show you a couple of other tricks that make this worth doing.
A Style for Print
When readers print out a website it comes with all the usual headings and navigation elements, however we can create another style sheet for use only when someone prints the page. To demostrate if we make a copy of the original style sheet called print.css.
Next go through and edit the sections that we don't want displayed inserting 'display: none' in place of the other properties.
div#logo {
display: none;
}
div#sect_nav {
display: none;
}
div#pagelinks {
display: none;
}
div#insert {
display: none;
}
This hides the parts of the page we don't want printed (I've created an example page with this print style only). However the mainpage area is still indented (and there is a green margin) so we need to edit the mainpage section to be 100% and remove the margin (overwriting all of the green).
div#mainpage {
width: 100%;
background: rgb(255,255,255);
}
And so we are left with a page that is clear of all the elements that are nice for the screen, but are unnecessary for the printed page. All we have to do is add an instruction to our page that tells a browser to use this different style sheet when printing, by specifying a media type with the style sheet.
<link rel="stylesheet" href="styles/print.css" type"text/css" media="print">
Save and we're done. A page that looks good on the screen, but prints well also.
Rollovers without Javascript
Rollover images are quite used extensively, but they rely on Javascript, which can be turned off, to swap one image for another. The navigation section on this page illustrates a similar effect using CSS. This combines the a:hover selector with a display: block property that allows us to change colours when a mouse hovers over the different links. To easily demonstrate this we'll modify the insert styles.
div#insert a {
font-family: Arial, Helvetica, sans-serif;
color: rgb(0,102,0);
background: rgb(255,255,255);
text-decoration: none;
text-transform: uppercase;
font-weight: lighter;
display: block;
border: solid 1px;
padding: 0.33em;
}
div#insert a:hover {
color: rgb(51,204,153);
background: rgb(51,204,153);
text-decoration: none
}
This results in a obvious rollover effect. In order to get things working elegantly the HTML and perhaps other styles would have to be tweaked - for example removing the <h1> tags from 'Lorem Ipsum' and removing the break tags...
<div id="insert"> Lorem ipsum <a href="http://tinyurl.com/378ja">What it means</a> <a href="http://www.microbion.co.uk/web/dwext.htm">DW Extension</a> <a href="http://www.websitetips.com/info/html/ipsum.txt">Text File</a> <a href="http://www.lipsum.com/">Generator</a> </div>
...then placing those styles into the main insert style (which is overridden by the link styles anyway)
div#insert {
width: 120;
float: right;
text-align: right;
font-family: Arial, Helvetica, sans-serif;
background: rgb(0,102,0);
font-size: 170%;
color: rgb(255,255,255);
font-weight: bold;
}
And because this will have an effect on the size of the links as well, we need to add a font size property to the links.
div#insert a {
font-family: Arial, Helvetica, sans-serif;
font-size: 60%;
color: rgb(0,102,0);
background: rgb(255,255,255);
text-decoration: none;
text-transform: uppercase;
font-weight: lighter;
display: block;
border: solid 1px;
padding: 0.33em;
}
Conclusion
I've tried to show a few different ways to use CSS in this workshop and this proves the flexibility of CSS and hopefully has you excited about rewriting your own sites.
Lastest 10 Threads - view all
Thanks for the good guide
Posted By: Hyomini at 18:22:12 on Tuesday the 14th of November 2006
Hi, thank you for the nice guide. This is going to help me a lot! :D
Excellent
Posted By: Matthew Cook at 11:32:18 on Thursday the 4th of August 2005
I have used your tutorial and code and modified it to make our intranet page fully CSS capable and whilst im still getting to grips with css, i found it most useful. Thanks very much .matt
Keith, your site is br0ken for me
Posted By: Chris MacAskill at 18:33:05 on Wednesday the 20th of July 2005
Hi Keith,
I'd love to love what you're saying, but in the latest Firefox and IE if you'd like to look at your site with larger fonts, clicking cntrl + completely breaks the layout.
And that seems to defeat the purpose of making it accessible to people who are over 40 and want to see the fonts larger, and defeats the concept of being able to change the site quickly.
Table-based sites like Amazon and eBay don't give me that problem. Is there a fix for this?
Thanks, Chris
Re: Keith, your site is br0ken for me
Posted By: marc at 19:53:59 on Wednesday the 3rd of August 2005
hi Chris and Keith -- i'd really like your input on this one as well Keith ...
your workshops are good Keith - thank you
Thanks & a question
Posted By: Arran at 10:48:10 on Friday the 1st of July 2005
Keith, the tutorial is great, just what I need to get out of the frame age! Pitched at just the right level.
one question if you wouldn't mind: I have a picture behind each of my links that matches up with the header to make 1 picture. Is it possible to remove or shrink border between links. Current code : *body*
*div id="logo"**img src="images/top.jpg" width="800" height="76" alt="Mud 2 Mud logo" /**/div*
*div id="sect_nav"* *img src="images/bar1.jpg" width="160" height="40" name="Contacts" border="0"* *img src="images/bar2.jpg" width="160" height="40" name="diary" border="0"* *img src="images/bar3.jpg" width="160" height="40" name="none" border="0"* *img src="images/bar4.jpg" width="160" height="40" name="links" border="0"* *img src="images/bar5.jpg" width="160" height="40" name="photos" border="0"* */div*
Thanks in advance
Arran
Re: Thanks & a question
Posted By: keith at 10:55:33 on Friday the 1st of July 2005
...if I am correct that is caused by the line breaks creating the whitespace. you can put the images all on one line OR you could splt the tag so that there is no line space:
*img src="images/bar1.jpg" width="160" height="40" name="Contacts" border="0"**img src="images/bar2.jpg" width="160" height="40" name="diary" border="0"*
HTH
Re: Re: Thanks & a question
Posted By: Arran at 13:41:41 on Friday the 1st of July 2005
Spot on. See you can teach an old dog new tables! Thanks
Great, but...
Posted By: Marius at 00:37:47 on Monday the 27th of June 2005
I've browsed the net for CSS, and I must admit that this article is very ncie and helpful. I've used CSS earlier a little bit, but nothing like in this article. I heard people talking about the table tag being replaced by CSS, and I didn't really understand how that was done. I searched the net and ended up at your site... Tables is the only thing I think has worked almost perfect in HTML. Many things in both HTML and CSS do not work in various browsers, or... they may work, but the webpages do not look the same. It seems like a lot of job to make pages with CSS, at least when we're talking about placing various objects on the screen (images ++) like you do in this article. When I tried your examples in Opera and IE, it was not looking the same. This has always been a problem with both HTML and CSS, and it will probably always be a problem in the future. I'll simply give up the whole web thing, at least the more advanced stuff.
Thanks for a good article.
Is this an error?
Posted By: Abhishek Ratani at 20:37:35 on Tuesday the 1st of March 2005
/* Set's Style for the Copyright Paragrh text */
div#copyright p { font-family: Tahoma, sans-serif; font-size: 90%; color: div#336633; margin-left: 5px; font-weight: bold; clear: both; }
color: div#336633;
Shouldn't it be color: #336633;
Thanks.
You have great tutorials by the way.

nice
Posted By: mike at 17:14:17 on Wednesday the 10th of January 2007
you're fucking stupid. this makes no sense
Reply to this comment