If you take a tour of the poorer neighborhoods in my neck of the woods, you’ll find a lot of single-wide trailers. They aren’t much to live in — they’re ugly, they’re crowded, they leak, they have no style whatsoever — but as domiciles, they’re functional. They work. You can live in one and keep body and soul together.
Drive a few hundred yards in any direction and you find neighborhoods of small, older houses that bear a startling resemblance to the trailer parks down the street. The oldsters around here call them "shotgun houses," named for the prosaic reason that you can fire a shotgun through the front door and the shot will fly through every room of the house before it exits through the back door. The basic floor plans of both are simple: one room "stacked" next to another, next to another, like a single row of alphabet blocks laid end to end.
Amateurs learn to make Web pages like these shotgun houses, except where the shotgun house is built horizontally, the Web page is built vertically. The elements are stacked one on top of the other, like that same row of alphabet blocks stacked vertically. That’s because most people learn HTML before they learn anything about Web design, and basic HTML is just marked-up text: take a chunk of text, mark it up, insert graphics and horizontal dividers hither and yon, and presto! You’ve got a Website.
For many people, this is enough. But for the rest of us, it’s only a beginning. We don’t want to design trailer-park Websites forever; we want to design cathedrals (or at least a nice two-bedroom bungalow with a little sun room and a breakfast nook)!
SitePoint is preparing to release Dan Shafers’ new book HTML Utopia: Designing Without Tables Using CSS. There are plenty of other cutting-edge articles on SitePoint about working with advanced table design, designing "beyond" tables, and the like. I recommend them highly, if you’re ready to step into such a rarefied atmosphere.
However, my "Practical Web Design" series is aimed at us grunts — those of us out there who aren’t really Webmasters (no matter what it might say on our business cards) and who aren’t ready for table-less Web design. With that thought in mind, I created this column. Hopefully, after you read this column and implement some of the material therein, you’ll be ready for the more sophisticated stuff. When that glorious day comes, SitePoint will be ready for you. Until that day comes… SitePoint is here to help you get there.
Note to veteran Web designers: this article covers ground you already know very well. Unless you find yourself in need of a refresher, you’ll probably want to skip it and read something more challenging. You might, however, find it useful in teaching someone else how to design tables.
The Basics of Table Design
Let’s get the basics out of the way first. There are hundreds of sites out there that will help you understand the basics of table layout; some of them are listed below, and there are plenty of others that are as good as, or better than, the ones I’ve included. Don’t forget the countless books on the local bookstore shelves, starting with HTML For Knuckleheads and going all the way through to cutting-edge design titles. I won’t attempt to duplicate the information available in these resources, but I’ll do a quick run-through of the various tags and design attributes of basic table layout. I recommend that you visit some of the sites listed below for additional help on understanding table construction.
Also worth noting: Marc Gugliuzza reminds us in his SitePoint article, Debate — Hand Coding: The Ultimate Freedom, that laying out tables by hand is probably the most difficult task to perform in HTML. If you’re not going to design a lot of Web pages, it might be worthwhile to use a WYSIWYG code editor such as Dreamweaver (pricey but excellent) or Arachnophilia (free and quite useful) to produce your table layouts. It takes some skull sweat to understand the ins and outs of tables — if it’s not worth your time, by all means let a program do the grunt work. But to quote Marc,
"…For those who are in the business of creating Websites, if you hand code, you will be better off than, and have an advantage over, the people who use WYSIWYG editors to write their code."
Web designers who use a program are at the mercy of their programs. Learning to code by hand gives you complete control over, and mastery of, the code.
Ok, back to it! Once you step into the wonderful, and wonderfully aggravating, world of tables, you’ve left the "shotgun house" paradigm of Web design behind. You’re graduating into a higher level of layout and design.
Take a look at the way your local newspaper is laid out. Ignore the content, just look at how it’s structured. It probably looks something like this:
This 3-column design with header is probably the most popular design style for most Web pages. Coincidence? Not at all. It’s very familiar to most users, who find the familiar design style comforting and easy to navigate. It works, and it makes sense. There are plenty of other design styles, including the even simpler 2-column design (getting rid of the narrow right column), and the more sophisticated "nested float" styles, among many others, but let’s not get ahead of ourselves.
I bet your newspaper’s Website is designed with the same 2- or 3-column style. In fact, I bet 9 out of 10 sites you visit use one variant or another of the 2- or 3-column design layout, if they don’t just use the "shotgun house" style of piling one item of content atop another ad infinitum. If it works so well, why muck around with it?
Vertical Vs. Horizontal Orientation
I don’t know about you, but I like vertical orientation. Phone books make innate sense to me because their structure suits me. If I’m looking at a cluster of tall buildings, I tend to look up the first, then over and down the next, and so forth.
When you’re first building Web pages, the structure of your page is innately vertical — you pile one thing on top of another, like a layer cake. But when you start thinking in terms of designing with tables, you have to break out of the vertical paradigm and start thinking in terms of rows, not columns. Across instead of down. You’ll see what I mean shortly.
As I said before, there are bazillions of sites out there that will help you with your table structure. For a thumbnail reference, I used SitePoint’s own Beginner’s HTML, Part 3 article by James Ussher-Smith to keep me honest. If you want something really user-friendly, try Lissa Explains It All: Tables for a well-done explanation of table construction. Lissa’s site looks like Ashley and Mary Kate designed it, but the information is valid and presented very well. I’d suggest you load one of those two pages and read them concurrently with this article. Lissa provides some very nice visual examples to accompany her tips.
Everything starts with the basic
<TABLE></TABLE> tag. These simple tags enclose a table structure, and tell the Web browser to watch out, table content is coming up.
You should be aware right now that browsers have to untangle a table’s entire structure before they display any of the table’s contents, so an overly fancy or loaded-down table structure will take some time to download and display. That’s why you click into a page and wait, and wait, and wait, while nothing seems to load, and suddenly bang! the entire page appears at once. It’s because the browser had to wend its way through a table layout before it could show anything. Table structures like this can aggravate the average site visitor, who may well click out to go elsewhere before the table can finish loading. Don’t force a single table to carry too much content, force it to be overly complex, or nest too many subsidiary tables inside one overarching, page-encompassing table. Better to use smaller tables and "stack" them one on top of the other.
Like so many other HTML tags, the
<TABLE></TABLE> tags act as "bookends" for your table content. Simple enough.
The next tag is the
<TR></TR> tag. This stands for "table rows." Rows, not columns. When I first started trying to make sense out of table structure, I kept running into a problem visualizing table structure because I wanted to think vertically, not horizontally. It took me more time than it should have to grasp the essential concept of table structure, because I didn’t want to think in terms of rows. I wanted to design "up and down," not horizontally. From my experience with other burgeoning Web designers, I’m not the only person who has run into trouble because of this paradigm shift. Trust me on this: once you make the shift from thinking vertically to thinking horizontally, tables become much, much simpler. And for those of you who naturally think horizontally, you’re entitled to a bit of a laugh at our expense.
<TR> tag indicates that a row is being created. The simplest form of table is the following (you might want to follow along by copying the code into Notepad, opening it in a separate browser window, and watching what happens as we move through this):
<TABLE> <TR></TR> <TABLE>
Hey, what happened to the row I just constructed? Nothing shows up! Well, we haven’t put anything in the row. A table needs cells, or compartments that store actual content. Think of a calendar. The typical calendar has four or five rows, with seven cells per row. You would think the code for a table cell would be
<TC>, but you’d be wrong. The code is
<TD>, for table data. Now let’s try that table structure again:
<TABLE> <TR> <TD></TD> </TR> <TABLE>
Arrggh! Still nothing! Well, not really. The structure is there, but since there’s no content, the table won’t display. Let’s put some content in that cell:
<TABLE> <TR> <TD>Bleah!</TD> </TR> <TABLE>
Now we’ve got something…a lot of code to display one nonsense word. Again, not really. You’re laying the groundwork for something a bit more complex. Let’s add some more cells:
<TABLE> <TR> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> </TR> <TABLE>
Besides being mildly childish, we’ve succeeded in making a word appear five times in succession. Well, no, we’ve done more. What you may not realize is that in HTML, the table structure itself is rendered invisible by default. In other words, you can’t see the borders. As with certain self-consciously modernistic calendars, you can only see the data. Well, let’s make the border show itself by adding an attribute to the
<TABLE> tag. Set the border value at 1, like so:
Now we’ve got something. Not only do we see the data, we see the table structure that contains the data. Before you go any farther, have a little fun changing the value of the border. Try 2, 10, 20, whatever suits you, just to see how big you can make that border. After you’ve exhausted the fun in that little exercise, return the value to 1 and settle in for the next step.
Basic design note: it makes life much simpler when laying out tables to keep the borders visible while you construct the tables. Your last step, before popping the champagne, can be to turn the borders off.
Of course you want multiple rows. So let’s do it. Wheee!
<TABLE border="1"> <TR> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> </TR> <TR> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> </TR> <TR> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> </TR> <TABLE>
Fun, huh? Now we’ve got three evenly structured rows of "bleahs" marching along our page. Add a few more rows and a few more cells, and you’ve got a nice structure for a calendar. Not bad for five minutes’ work.
Let’s throw some monkey wrenches into our nice, neat (but limited) table structure. We’ll start by noticing that the cell sizes conform to the content therein — in other words, the cells adjust themselves to fit comfortably around the content, with no wasted space. And since the content is the same in all the cells, the table has a nice, even structure. Let’s change that.
In the second row, third cell, change the content to read:
Notice what happens. That cell lengthens itself to accommodate the longer word, but so do the cells directly above and below that particular cell.
If you break the magic word into two parts, using a line break:
the cell becomes twice as high or as deep, depending on how you look at it. So do the cells in the entire row. Get used to how tables automatically adjust themselves, and you can save yourself a lot of time and trouble designing and redesigning the same table to appear how you want.
Aligning Your Cell Contents
You also notice that the text in the center row automatically aligns itself to the left side of the cell. That’s the default. Let’s change it using the align attribute. Try it with the cell just to the left of the "Abra Cadabra" cell:
Now the word is centered in the cell. Want every word in that row center aligned? Instead of painstakingly aligning each cell’s content, just add the attribute to the row instead:
It looks the same as before, but trust me, if and when the contents of the rest of that row’s cells get some space to play with, they’ll all center themselves instead of defaulting to the left.
There’s also the
VALIGN attribute, which looks very similar, but acts quite differently. For one, it’s an attribute that works with an entire table (i.e. the
<TABLE> tags), not the rows or cells. The default is to place the information in the center, with equal space above and below. Most people learn to lean heavily on the
<TABLE valign="top"> attribute, which forces the content to align itself vertically from the top. If you have two vertical columns of content that contain unequal amounts of content, you don’t want the "shorter" column to have its content shoved down into the center of the column, leaving an unsightly empty space at the top. Force the content to the top with the
VALIGN attribute, and let the bottom of the column have the empty space.
Cellpadding and Cellspacing
Let’s go back to our nonsense table. We might want to give the content in those cells room to breathe — in other words, set it off with some whitespace so that it doesn’t appear constricted by the table borders. Use the
CELLPADDING attribute to give your content some elbow room. Try this in your
Ahhh, room to breathe! Feel free to play with the padding value to give yourself as much or as little room in the cells as you like, but remember that the padding works indiscriminately — in other words, you can’t align one cell’s content against the left border while using a pad, because the pad won’t give way.
Now, let’s add some space between the cells themselves, using the
<TABLE cellpadding="5" cellspacing="5">
Notice how the border itself gets larger? This gives a different appearance than does using the
BORDER attribute to make the border larger, and provides whitespace even when the
BORDER attribute is set to 0.
Okay so far? Good, now let’s get messy. So far we’ve created a group of identical cells that trundle along the page one after another with no variance. This is all well and good, but we can do more. Meet the
ROWSPAN attributes. These are fairly obvious — they cause cells to "span," or stretch across, a column or a row.
Let’s add a
COLSPAN attribute to the first
<TD> line of our nonsense table:
Well, that threw things into a tizzy. Your first cell "spans," or stretches over, the first two cells in the second row, and everything else moves to accommodate the stretched cell. One poor fellow is stranded alone, in a column by itself. Essentially, what you’ve done is made one cell occupy the space of two cells, so the table treats it as if it were two cells.
Let’s add the
COLSPAN attribute to the other rows to compensate, and see if we can tidy things up a bit:
<TABLE border="1" cellpadding="5" cellspacing="5"> <TR> <TD colspan="2">Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> </TR> <TR> <TD>Bleah!</TD> <TD colspan="2">Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> </TR> <TR> <TD>Bleah!</TD> <TD>Bleah!</TD> <TD colspan="2">Bleah!</TD> <TD>Bleah!</TD> <TD>Bleah!</TD> </TR> <TABLE>
Well, that’s a bit more symmetrical. See how they position themselves?
Now, let’s see what happens with the
ROWSPAN attribute. Get rid of all the
COLSPAN attributes and change the first
<TD> line to read:
As you might have expected, the first cell stretches downward two rows, and everything else shifts to compensate… once again, leaving a single cell stranded.
Take some time to experiment with the two attributes, singly and in combinations. You can make one heck of a mess of your table, but you can also get a feel for how they work.
Coloring Your Tables
It’s quite simple to add color to your table structure. You can color the table border itself, or add color to the cells.
Color the border itself with the
<TABLE border="1" cellpadding="5" cellspacing="5" bordercolor="#ff00ff">
This turns the lines of the border a nice… magenta? Change the thickness of the border to give the entire table a thicker frame:
<TABLE border="5" cellpadding="5" cellspacing="5" bordercolor="#ff00ff">
Use the familiar
BGCOLOR attribute in your cells to change the color of the cells themselves:
Experiment with different color combinations to see what appeals.
You can also use the
BACKGROUND attribute to put a background image in your table, either in your entire table:
<TABLE border="5" cellpadding="5" cellspacing="5" background="image.gif">
or in a specific cell:
One neat use of a table, as suggested by Lissa, is to frame a graphic with a colored border:
<TABLE border="5" bordercolor="9966ff"> <TR> <TD> <IMG SRC="image.gif" width="100" height="100" alt="image"> </TD> </TR> </TABLE>
You can even use two tables, one inside the other, to make a double border:
<TABLE border="5" bordercolor="00ff00"> <TR> <TD> <TABLE border="5" bordercolor="9966ff"> <TR> <TD> <IMG SRC="image.gif" width="100" height="100" alt="image"> </TD> </TR> </TABLE> </TD> </TR> </TABLE>
See how the interior table fits inside a single cell of the outer table? This is one example of "nesting" tables. In this example, the nested, or interior, table is just used to provide a border, but using nested tables one inside of the other is a terrific way to handle more complex page layouts. And, speaking of page layouts…
Using Tables to Make a Basic Page Layout
Tables constrain themselves to fit the content they contain, unless you tell them differently. You can do this simply enough with the
WIDTH attributes for the
<TABLE> tag. There are two flavors of
WIDTH: absolute and relative. The first creates a table that is an absolute width as measured in pixels, like so:
<TABLE width="744" height="410">
This is optimized for the average 800×600 screen display. It will fit nicely within the display both horizontally and vertically, with just a bit of "cheater" space left over for slightly off-sized displays. Unfortunately, it is just what it says — an absolute value. Therefore, those folks using other displays won’t see a nice table that fills their screen. The folks with a 1024×768 display will see a table in their screen, but will have plenty of unused real estate surrounding it; those few still laboring with a 640×480 display won’t see the entire table, and will have to scroll both horizontally and vertically to see all the content. Not good.
A better option for the average table designer is using relative table heights and widths. These use percentages instead of pixel values, to wit:
<TABLE width="95%" height="95%">
This fills up 95% of the available display space both horizontally and vertically. Leave one out (typically the
HEIGHT attribute), and the table sizes itself to take up 95% of the screen horizontally, but automatically adjusts itself to fit the content vertically. This last option, using a
WIDTH percentage but letting the
HEIGHT take care of itself, is usually a good choice to go with.
Here’s the basic table layout of my own site. I didn’t do anything fancy or groundbreaking — in fact, when I originally designed the page, I had only the fuzziest notion of how to use tables to lay pages out. So I opted for something simple that I could get my mind around, was user-friendly and familiar. So here’s what I did (aping who knows how many other Web pages):
Here’s the code, minus the content. Notice that I’ve centered the entire interior, or nested, table:
<TABLE width="600"> <DIV ALIGN="center"> <TABLE> <TR> <TD width="20%"></TD> <TD width="5%"></TD> <TD width="70%"></TD> </TR> </TABLE> </DIV> </TABLE>
Notice that the
<TD> widths add up to 95%. That gives me 5% of my display width to "cheat" with, providing a slender whitespace margin on the left and right sides of the display.
There are some issues with this page layout. I originally chose to use a "framing" table with a 600-pixel width because at the time I designed it (around 2001), many of my users let me know they were still using 640×480 displays, and I wanted my page to fit in their displays without the annoying horizontal scroll bar. I’ve asked my newsletter subscribers what they used, and enough of them still use the smaller displays for me to rationalize keeping the width at 600. If I were designing the page today, I’d set the pixel width around 740 or so.
And let me reiterate, there’s nothing outstandingly wonderful or different about the page layout I’ve used. I used it as an example simply because it’s a scheme with which I’m familiar. The usability gurus such as Andy King and Jakob Nielsen would have a field day picking my page apart. However, it serves as a starting point. You can set yourself an exercise: improve on it!
I’ve decided that, rather than redesigning the page with a different table layout, to wait until I’ve mastered CSS enough to redesign the page using the more modern style-sheet driven, tableless design methodology. Since I haven’t mastered CSS well enough to do that yet, and since a large percentage of my audience continues to use older PCs and browsers that choke on modern CSS, my page stays rooted in pre-millennium table design for now. But hey, it works, and for the moment, that’s good enough for lazy old me.
Part II of this article will focus on less-used
TABLE attributes, many of them introduced in HTML 4.0, and some other fun things to do with tables. See you next time!