How can I make just one cell in an HTML table bordered, or just one side of a cell bordered?

For HTML tables, you can use the border attribute to suggest the width of a border around the table and each cell. There are other methods defined in HTML 4 to suggest cell borders (or "rules", as they are called there) as separate from the overall border for the entire table. Such methods don't work e.g. on Netscape 4 for example, though, and moreover they cannot be used to suggest that borders should appear around a single cell only, or even on one side or some sides of a cell only. This document briefly discusses some HTML hacks like nested tables that might be used, and then the more reasonable style sheet (CSS) approach.

HTML hacking: nested tables

For simplicity, let us consider a trivial table with three cells:

<table border="1" cellspacing="0" cellpadding="4">
<tr> <td>one</td> <td>two</td> <td>three</td> </tr>
</table>

This is how it looks like on your browser:

one two three

The cellspacing and cellpadding attributes are mostly not relevant to our discussion, though you probably want to tune their values to suit your table content. But note that using style sheets you could suggest padding properties for an individual cell if you like. So you could e.g. set cellpadding to zero and use the CSS padding properties to suggest the paddings you like, with the implication that in non-CSS browsing situations there would be no padding.

Now let's first assume that we would like to remove the borders except for those surrounding the second cell. There is no direct way to do that in HTML. But one possible approach is to set border="0" and construct a border for the second cell by making the cell content a single-cell table, with a border of its own:

<table border="0" cellspacing="0" cellpadding="4">
<tr> <td>one</td>
     <td><table border="1" cellpadding="4">
        <tr><td>two</td></tr></table></td>
     <td>three</td> </tr>
</table>

This is how it looks like on your browser:

one
two
three

Nested tables are valid HTML. The reason I call using nested tables a hack here is that the inner table isn't really much of a table, and it is used for presentational purposes only, and it distorts the logical structure - that is, the markup does not correspond to the intrinsic structure of the data. But it's a fairly innocuous hack. Used with syntactically correct markup and with all the end tags like </td> written explicitly, to avoid Netscape bugs, it should be fairly safe. But not totally safe. It is possible that some programs will process the document according to the way you have indicated in your markup, and therefore treats the content cell as a table, whatever that might mean in each content.

What if you would like to affect the appearance of the border: its color and shape? Well, using a modification of the nested tables trick, you could make the border solid and have a specific color. (Under the usual caveats of course; a browser might be configured to ignore colors suggested on pages, or the monitor might be incapable of displaying the suggested color, etc.) The idea is to use padding inside a cell for creating the impression of a colored border. This means that you would use border="0" for the inner table too but use a nonzero cellpadding for outer table to create some border-like space between the cell content (the inner table) and the invisible (or zero-width, just as you like it) cell border, and a bgcolor attributes for coloring that space.

<table border="0" cellspacing="4" cellpadding="2">
<tr> <td>one</td>
     <td bgcolor="#006600">
        <table border="0" cellpadding="4" cellspacing="0">
        <tr><td bgcolor="#ffffff">two</td>
        </tr></table></td>
     <td>three</td> </tr>
</table>

This is how it looks like on your browser:

one
two
three

It's somewhat complicated. Note that the cellpadding attribute of the outer table specifies the width of the "border" whereas the cellpadding attribute for the inner table specifies the padding around its content. The bgcolor attribute for the cell ("#ffffff", i.e. white, in our example) should normally be the same as the overall page background or the table background color, but it could be different too, of course, if you wish to achieve a special effect.

Things get even more complicated if you wish to make just one side, or just some sides, of the the cell bordered. Let's consider a simple case where you would like to have a border just on the left side of the cell. Then you could just add a "dummy cell" into the table and try to make that cell look like a border - for example, a two pixels wide empty cell which has the dark green background. This raises some problems, but they are discussed separately in the document Empty cells in HTML tables, so here we just make use of the technique explained there:

<table border="0" cellspacing="4" cellpadding="0">
<tr> <td>one</td>
     <td bgcolor="#006600" width="2"><img
        src="../images/transp.gif" width="2" alt=""></td>
     <td>two</td>
     <td>three</td>
</tr></table>

This is how it looks like on your browser:

one two three

Note that cellpadding has been set to zero, since that attribute affects the "dummy cell" too, and a nonzero value would make it wider than you want. (If you use <td width="2"> for example, a browser could still, quite meaningfully, use a wider cell if the cell padding requirements alone make it necessary.) So the spacing between cell contents, including the "dummy" cell and its neighbors, comes from the cellspacing attribute alone. This may cause problems, since cellspacing affects in vertical direction too, so the spacing between rows might become too large. As you may guess, nested tables could be used as a workaround. (You could make the cell content a table, consisting just of the dummy cell and the real cell content.) But I think it's time to move to methods which are not inherently that hackish, though they too require some tricks if you wish to achieve maximal browser coverage.

Using style sheets for cell borders

Using stylesheets (CSS), it is in principle very easy to suggest borders for a cell. You would just assign a style sheet rule to it, using the border property, or related properties. Using an "embedded" style sheet in a style attribute (not the best way, but will do for our illustration), you could write just

<td style="border:solid 2px #060">

You wouldn't then use any border attribute in HTML, expecting the border to default to zero, or you might explicitly write <table border="0">. Note that in color specifications in CSS, you can use handy short forms like #060 for #006600 (which is acceptable too in CSS).

If you would like to have a border just on the left size, you would simply use border-left instead of border there.

Here's a simple test, with left border suggested for the second cell:

one two three

If you're using, say, Internet Explorer 4 or Opera 4, you'll probably see the border there, unless your browser settings prevent that. On Netscape 4, you won't. On the other hand, you might be perfectly satisfied with having your table shown the preferred way in most browsing situations and without that border in a minority of cases. (After all, you can never control such things as an author, anyway.) Then you can keep your markup and your style sheet simple and nice and logical.

But it is possible to cover Netscape 4 too, with some added complexity. Among the many bugs in CSS implementation on Netscape 4, there are two problems that are particularly relevant here: Netscape has problems with applying styles to table cells, and it does not support properties like border-left. As a workaround to the former, we can wrap the cell content into div markup and assign the style sheet rules to it. As to the latter, we can use the border shorthand property (which partly works on Netscape) to suggest a border with the desired color and border style but zero width, and use the border-left-width property (which, oddly enough, partly works on Netscape) to suggest that the left border have a nonzero width:

<table border="0" cellspacing="0" cellpadding="4"><tr>
  <td>one</td>
  <td><div style=
   "border: solid 0 #060; border-left-width:2px; padding-left:0.5ex">
    two</div></td>
  <td>three</td>
</tr></table>

This is how it looks like on your browser:

one
two
three

The padding-left property is used here to prevent the border from hitting the content. Since the border is not for the td element now but for the div element inside it, the cellpadding affects the padding between that border and the (invisible) cell border, not between the border and the content of the div element. But this is really no problem, since padding-left is well supported by CSS enabled browsers.

What might be a problem is that the border might not extend vertically to fill the entire cell, since it's a border for div element inside the td element and the cellpadding attribute affects the padding vertically too. If this is a problem, consider setting cellpadding to zero and using CSS for any padding you like. Note that in a style sheet (inside a style element, not attribute, or in a separate file) you could simply write, say,
td, th { padding: 0.5ex; }
to set the default padding inside all cells to 0.5ex, and then perhaps override that for some cells if desired.

To end with a word of warning: It is advisable to close all table-related elements explicitly with end tags like </td>, </th>, </tr> and </table>, even though some of them are formally optional according to HTML specifications. I have managed to crash Netscape with a fairly simple construct just because I did not follow that advice.


Date of last update: 2000-11-16

Jukka Korpela