In most CSS circles, you'd think table was a dirty word. Its being constantly pounded into every web developer's head to not use tables for layout. Which is true, you shouldn't use tables for layout. However, you should use tables for tabular data. That's exactly what they are intended for.
Recently, while doing just that for a large web project, I tried to use table captions on some data tables. What I discovered was that various browsers deal with table captions in some very different ways. So different, in fact, that it was necessary to do some research and testing on how browsers display tables and captions and which properties are supported. And once I'd wrapped my head around the table display model concept and figured out which browsers did what, it became necessary to figure out how to overcome those differences in order to come up with a single workable blueprint for displaying all of the tables in my project.
This page uses an HTML 4.01 Transitional DocType. For purposes of this page I have chosen to use a fixed table layout with a declared table width of 300px and a border-collapse: collapse. In my limited testing, the results appear to be the same for an auto table layout. I'm not going to spend much, if any, time discussing how to style the table itself. There are plenty of resources for that, including Eric Meyer's "Cascading Style Sheets: The Definitive Guide" and other CSS books and online sources. We are primarily concerned with the table caption because there is a great deal of difference in how table captions are displayed across browsers and because there is little information about them.
According to the CSS2.1 specs, the table caption should be displayed as a block level element and inherits properties from the table it is a part of (table and caption boxes do however retain their own “content, padding, margin and border areas”). The caption is only allowed to be placed at the top of the table in the actual HTML code. You would use caption-side to assign where the caption actually appears with a value of top or bottom (left and right are deprecated values that were in CSS2.0 but dropped in CSS2.1, so I won't be including their use here).
In reality the display of table captions varies by browser. Below is a series of examples illustrating various bugs and differences in rendering table captions. You will need to view this page in each of the mentioned browsers in order to see their related issues.
Its important to note that, according to the CSS 2.1 specs:
The default style sheet for HTML 4.0 in the appendix illustrates the use of these values for HTML 4.0:
table { display: table } tr { display: table-row } thead { display: table-header-group } tbody { display: table-row-group } tfoot { display: table-footer-group } col { display: table-column } colgroup { display: table-column-group } td, th { display: table-cell } caption { display: table-caption }User agents may ignore these 'display' property values for HTML table elements, since HTML tables may be rendered using other algorithms intended for backwards compatible rendering. However, this is not meant to discourage the use of 'display: table' on other, non-table elements in HTML.
Firefox and Netscape 7.2 strictly adhere to the CSS2.1 specs regarding tables and captions. They recognize the caption-side values of top and bottom and correctly place the caption where expected. A typically styled table is shown below in Example 1.
This example has caption-side:top applied. If you're viewing this in Firefox 1.0 or Netscape 7.2, you will notice that the margin border is off by one pixel on the left hand side. You will only notice this incongruity if a background color and/or border are assigned to the caption. All the tables on this page use the collapsing border model [1]. In this model the width of the table includes half the table border on each side of the table. the other half of the border protrudes into the margin area of the table.
Since the caption lies within the table itself and we've not assigned a specific width to it, its width is equal to the total width of the table. Since a 1px border has been specified for the table, and the total table width includes half the border, the computed caption width ends up being 1 pixel less (1/2 from the left and right borders respectively), resulting in the 1 pixel difference. Since a 1/2 pixel cannot be rendered on-screen, Firefox adds the two half pixels together and stick the resulting pixel space on the left border. [2]
Internet Explorer 6 and Opera 7.54 both ignore this rule and render the table as you'd expect visually, even though it is wrong according to the CSS 2.1 specs.
It is also important to notice that the bottom border of the caption is collapsing into the top border of the table in Firefox 1.0, Netscape 7.2 and Internet Explorer 6. Opera, however, does NOT collapse the border, which appears to be the correct behavior according to the CSS 2.1 specs.
| LName | FName | Dept | Phone |
|---|---|---|---|
| Anderson | Mark | 001 | 123-4567 |
| Blagg | Glen | 002 | 123-4567 |
| Chesnutt | Jeff | 003 | 123-4567 |
| Cruz | Hector | 004 | 123-4567 |
This example shows how to fix the 1-pixel margin error in Firefox 1.0 and Netscape 7.2. Simply assign a margin-left:-1px; to the caption. You might think this would cause a problem with Internet Explorer 6's rendering of the border, but fortunately for us, Internet Explorer 6 ignores margins applied to captions, so this table now looks identical in both Internet Explorer 6 and Firefox 1.0. [3]. Unluckily, Opera 7.54 doesn't like this negative margin on the caption and fails to render the caption at all! It does however reserve the space that the caption would take up in the layout.
| LName | FName | Dept | Phone |
|---|---|---|---|
| Anderson | Mark | 001 | 123-4567 |
| Blagg | Glen | 002 | 123-4567 |
| Chesnutt | Jeff | 003 | 123-4567 |
In CSS2.0 there were four values that could be assigned to the caption-side attribute; top, bottom, left, right. Due to lack of support, right and left have been dropped from CSS2.1 leaving us with just top and bottom.
Firefox 1.0 and Netscape 7.2 correctly position the caption according to this assigned value. In Example 3a below, the caption-side value has been set to bottom. If you're viewing this in Internet Explorer 6 or Opera 7.54, the caption is still at the top, since both of these browsers ignore the caption-side completely, always placing the caption at top. [Note that the -1px left margin on the caption has been removed here so that Opera will show the caption.]
When viewing in Firefox 1.0 and Netscape 7.2, you may notice that the caption has some space between it and the bottom of the table cells above it, contrary to what you might expect. This is because these two browsers follow the spec which specifies that the table and the caption have separate margins. According to the CSS2.1 specs [4]:
the table element generates an anonymous box that contains the table box itself and the caption's box (if present). The table and caption boxes retain their own content, padding, margin, and border areas, and the dimensions of the rectangular anonymous box are the smallest required to contain both. Vertical margins collapse where the table box and caption box touch. Any repositioning of the table must move the entire anonymous box, not just the table box, so that the caption follows the table.
To better understand this, its best to view a diagram showing how margins are applied to the table and caption element.
Once again Internet Explorer 6 ignores margins on the caption, and so is unaffected other than misplacing the caption at the top rather than the bottom.
Opera 7.54 also ignores the margins on the caption, leaving you with only the non-collapsed bottom border as an issue to deal with.
| LName | FName | Dept | Phone |
|---|---|---|---|
| Anderson | Mark | 001 | 123-4567 |
| Blagg | Glen | 002 | 123-4567 |
| Chesnutt | Jeff | 003 | 123-4567 |
The correct way to fix the margin issues with Firefox 1.0 and Netscape 7.2, as shown in Example 3.B below, is to assign a margin-bottom:0; to the table, and assign a margin-top:0; value to the caption as well as a margin value for the rest of the caption that is the same dimension as the table margin itself. But wait! Don't forget about that one pixel border rendering issue with the left side of the caption in Firefox and Netscape! That means we have to assign one less pixel to the lefthand margin. It should also be noted that in Firefox and Netscape, the top border of the caption won't collapse when the caption is positioned at the bottom (though they do if the caption is positioned on top). Ignoring Opera for the moment, here is what we need to do:
table {
caption-side:bottom;
margin:5px;
margin-bottom:0;
}
And for the caption:
caption {
border:1px solid #333;
border-top:none;
margin:5px;
margin-left:4px;
margin-top:0;
}
Its best to assign table margins in pixels so that we can have a margin-left value one pixel less than the rest of the margins to compensate for the one pixel left border issue with Firefox and Netscape. Luckily for us, having a margin-left value one pixel less has no effect in Opera, since its not a negative value, so Opera at least renders the caption.
If you view Table Ex 3.B in Internet Explorer 6 you may notice that we are now missing the top caption border. Since Internet Explorer incorrectly places the caption at the top even when we've positioned it at the bottom, we're going to need to feed IE a different value for the caption's border-top. Luckily, Internet Explorer ignores the margin values, so we only have to deal with the top border for that browser.
However, we're not as lucky in Opera 7.54. Opera incorrectly places the caption at the top of the table, omits the top margin, and applies the margins we assigned to the caption. To fix all of this, we're going to have to feed Internet Explorer 6 and Opera different values for the top border and margins.
| LName | FName | Dept | Phone |
|---|---|---|---|
| Anderson | Mark | 001 | 123-4567 |
| Blagg | Glen | 002 | 123-4567 |
| Chesnutt | Jeff | 003 | 123-4567 |
Because of the different ways each of the four browsers we've tested deal with displaying table captions, our options are limited. Essentially, we have no choice but to leave the caption placed at the top of the table. This leaves us with two problems to deal with; the margin issue in Firefox/Netscape and the non-collapsing bottom border in Opera. This is by far the easiest choice. To deal with the margin issues, we need to feed the -1px left margin value to Firefox and Netscape while simultaneously feeding Opera a 0px left margin value. This calls for the employment of the @media hack for Opera, shown below:
@media screen and (min-width: 0px) {
#ex4a caption {margin-left:0}
} /* Opera 6+ specific value */
To eliminate the non-collapsing bottom border, we simply assign a border-bottom:0; value to the caption. This has no effect on Internet Explorer, Netscape or Firefox which all collapse the border anyhow, and eliminates the double border in Opera. Ex. 4.A below shows the results.
| LName | FName | Dept | Phone |
|---|---|---|---|
| Anderson | Mark | 001 | 123-4567 |
| Blagg | Glen | 002 | 123-4567 |
| Chesnutt | Jeff | 003 | 123-4567 |
If you need to have margins surrounding your table then things are a bit more complex, but not by much. To deal with the left margin issue, we simply assign a margin in pixels to the table, assign top and right margins to the caption of equal value, and assign a left margin one pixel less than the left margin of the table. That leaves only Safari's right margin to deal with which I'm not able to test.
The problem child is Opera 7.54. It adds margins to the caption as if the caption were within the margins of the table. The result is that the left and right margins of the caption push inwards, making the caption appear smaller in width than the table cells below it. Fortunately we can once again employ the @media screen hack to feed specific values to Opera:
/* Opera 6+ specific values inserted here */
@media screen and (min-width: 0px) {
#ex4b caption {
margin-left:0;
margin-right:0;
}
}
Since Opera applies the table margin around the caption anyhow, we can feed 0 margin values to the caption and still preserve the overall margins around the entire table, caption included.
| LName | FName | Dept | Phone |
|---|---|---|---|
| Anderson | Mark | 001 | 123-4567 |
| Blagg | Glen | 002 | 123-4567 |
| Chesnutt | Jeff | 003 | 123-4567 |
If you have a border larger than 1 pixel, you're in for some additional surprises. Ex 4.C shows what happens when we apply a border of 10px to the table and caption.
| LName | FName | Dept | Phone |
|---|---|---|---|
| Anderson | Mark | 001 | 123-4567 |
| Blagg | Glen | 002 | 123-4567 |
| Chesnutt | Jeff | 003 | 123-4567 |
If you view Ex 4.C in Firefox or Netscape, what you see is the difference in the way borders are applied to the table and the caption. The caption border is applied half outside and half inside the caption box. Since you want the borders to line up, you can't reduce them in size. Instead, you need to reduce the left and right margins of the caption, following this formula: caption margin = table margin - 1/2 caption border.
In this case, we have a 10px table margin and a 10 pixel caption border, so 10px - 5px = 5px caption margin. We need to adjust the right and left margins of the caption to 5px each. See the results below in Ex. 4.D. Note how we no longer have the 1 pixel border shift in Firefox and Netscape. This is because the total border width is an even number, 10.
Opera on the other hand draws the caption borders completely within the table space because of the way in which it draws the margin values, just like before. Once again, we need to feed Opera different margin values:
/* Opera 6+ specific values inserted here */
@media screen and (min-width: 0px) {
#ex4d caption {
margin-left:0;
margin-right:0;
}
}
An extra amount of padding was added to the caption as well, to keep it away from the bottom border, as the caption continues to collapse into the table (in other words the table's border intrudes into the caption's space). The extra padding helps Firefox, Netscape and Opera maintain vertically centered caption contents, but in Internet Explorer, which does not push the table border up into the caption, it just results in extra padding on the bottom of the caption.
| LName | FName | Dept | Phone |
|---|---|---|---|
| Anderson | Mark | 001 | 123-4567 |
| Blagg | Glen | 002 | 123-4567 |
| Chesnutt | Jeff | 003 | 123-4567 |
Below is another example with a table and caption border of 3 pixels applied. This one is trickier. Table margin is 10px, and the border is 3px, so 10-1.5 = 8.5px. Well, we can't specify an 8.5px margin. This is basically the same problem introduced with a single pixel border and we can solve it the same way. Our right margin should be 9px and our left 8px because Firefox renders the extra pixel space on the left side. Of course we use our hack to feed Opera 0px left and right margin values.
| LName | FName | Dept | Phone |
|---|---|---|---|
| Anderson | Mark | 001 | 123-4567 |
| Blagg | Glen | 002 | 123-4567 |
| Chesnutt | Jeff | 003 | 123-4567 |
The CSS2.1 specs state that the caption should inherit values from the table itself. It also states that each will have its own border, padding and margins. Below is a table showing which values are inherited by which browser. You can override most of the inherited values by specifying values in the caption itself.
| Attribute | Inherited? | Notes |
|---|---|---|
| margin | no | See example 3 above for how table margins affect captions. |
| border | no | Opera 7.54 does not correctly collapse the bottom caption border when the caption is positioned at top and the border is 1 pixel. |
| padding | no | |
| background-color | no | |
| text-align | no | |
| font-family | yes | |
| font-size | yes | |
| color | yes | |
| font-weight | yes |
[1] - Roger Roelofs points out that Internet Explorer 5.2/Mac ignores the border collapse attribute altogether. This is a fairly harmless thing, but it does introduce some space between cells. As they say, life isn't perfect.
[2] - thanks to Bruno Fassini for pointing this out. He also noted that Safari computes the width of the caption the same way, but shows the 1 pixel gap on the right of the caption. On page 348 of Eric Meyer's book "Cascading Style Sheets: The Definitive Guide", 2nd Edition, he notes that "In cases where a border is an odd number of display elements...wide, the user agent is left to decide what to do about centering the border on the grid line. It might shift the border so it is slightly off-center, round up or down to an even number of display elements, or anything else that seems reasonable." IE and Opera round it up, Netscape and Firefox render it off-center to the left, and Safari renders it off-center to the right.
[3] - As Bruno notes in [1] above, Safari applies this 1 pixel gap to the right of the caption. The negative margin fix extends the margin 1px beyond the table border on the lefthand side in Safari, while leaving the righthand caption indented 1px.
[4] - A huge thank you to Philippe Wittenbergh who has gone out of his way to help me understand the effects of margins on tables and captions and for various other contributions. Hats off. Philippe also notes that Safari/OmniWeb both ignore the bottom margin when the caption-side is specified as bottom.
My name is Ron Pringle and I'm the web developer for the City of Aurora, IL. While redesigning the city's website I came across some problems with displaying captions on data tables via CSS, and started poking around trying to figure out the answer.
I live on the CSS-Discussion list. If you have comments or questions about this page, you can post them there or send me email at rpringle at aurora dash il dot org. I hope this page helps you out and solves some of your problems for you.
An especially big thanks to all the people on the CSS-D list who have helped me out with this and many, many other CSS problems.