Style tables with CSS
I don’t deal too much with tables. Not because I don’t want to but because clients hardly ever want to use them. My guess is that they are too hard to create with todays WYSIWYG editors, and therefore get left out. It happens though that I have one or two static tables I need to style, and then I get to use a couple of my tricks.
All of the examples below work across browsers. Including IE6.
- Add a gradient to your cells
- Remove the space between the cells with CSS
- Obey the set width
- Styling columns
Add a gradient to your cells
One easy way to make tables look better is to add a subtle gradient to the cells. That’s easy to do. But make sure you also set a background color with one of the edge colors from the gradient, and use the top or bottom keyword. You never know the height of your cells when people zoom the text.
td {
background: #2B2B3C url(item_gradient.gif) repeat-x bottom;
}Remove the space between the cells with CSS
When designing tables you rarely want the ugly double border between two cells that appear when you set a border on td. Neither do you want the space in between them… Many believe the only way to remove that space is to use the cellspacing and cellpadding attributes in HTML. You don’t:
table {
border-collapse: collapse;
}
td {
border: 1px solid silver;
}See? No ugly HTML attributes needed.
Obey the set width
Many of you have probably seen tables that do not stay within the width you have set on them. It can be long words or sometimes URLs that are wider than what can fit. By default, the browser puts content before style, and therefore expands the table to show the content. But what many don’t know is that you can change them to always obey the set width:
table {
table-layout: fixed;
width: 100px;
}Easy, and now the table will be 100px, no matter what.
Styling columns
Sometimes you want to style some columns differently than all other cells, and I’ve seen that most people add a special class to each of the cells in that column. Wouldn’t it be nice if there was a way to just specify the class once? There is!
<table>
<col class="first">
<col class="second">
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
</table>col.second {
width: 100px:
}Convenient isn’t it? There’s one thing you should know though… The col attribute only allows four attributes: Border, Background, Width, and Visibility. What the heck? Well, there is performance issues with implementing more complex things so W3C decided not to include it. So what if you need to set, say, text-align on a column? You can be clever:
col.second {
text-align: right;
}
td:first-child + td {
text-align: right;
}The above works because IE allows setting more properties on columns than the spec allows (Hixie explains it well). Firefox on the other hand, ignores the set text-align, but instead allows you to use a sibling selector to select the “second td after the first one” (you can add another “+ td” to select the third one, and so on…). Voilá! Cross browser column specification.
That’s all for now, did you know all of them?
Robert Nyman (33 comments) ( 14 Mar 2008 )
Good write-up.
As we’ve seen in a mutual project, border-collapsing doesn’t work properly in Firefox, when the table has a 100% width and a border itself
Emil Stenström (605 comments) ( 14 Mar 2008 )
@Robert Nyman: I remember the case of the disappearing outer border. But there were many more variables to fuck things up there. If you get to that point, then sure, use your cellspacing attribute :)
Nita (5 comments) ( 14 Mar 2008 )
Nice overview, thanks! But isn’t it “border-collapse”? :)
madr (7 comments) ( 14 Mar 2008 )
The trick with using COL has crossed my mind now and then for about two years now, but I never tried it – as you said, one does not use tables that much.
Nice to see that CSS does as one can expect it to. :)
Really good writeup anyways. I will definitely show this to my collegues – since they tend to classitis all tables.
Emil Stenström (605 comments) ( 17 Mar 2008 )
@Nita: It sure is, thanks for correcting me :)
unwiredbrain (4 comments) ( 18 Mar 2008 )
Watch out! It’s not ‘border-collapsing’, it’s ‘border-collapse’: http://www.w3.org/TR/CSS21/tables.html#propdef-border-collapse
unwiredbrain (4 comments) ( 18 Mar 2008 )
Err… :-\ I was reading the pre-updated. But after the update it still looks buggy! :) :P
Emil Stenström (605 comments) ( 18 Mar 2008 )
@unwiredbrain: Thanks, but it should be correct now, I’ve double-checked.
unwiredbrain (4 comments) ( 18 Mar 2008 )
Really… I don’t want to be dull, but what I see is ‘border-collape’…
Or you’re missing a ’s’ or you want mokeys in your codes! :) :P
Have a nice day.
Peace & Love
–
uwb
Emil Stenström (605 comments) ( 18 Mar 2008 )
@unwiredbrain: Ehmm… I don’t see any missssspellings? Thanks again…
unwiredbrain (4 comments) ( 19 Mar 2008 )
OK. now the code section 2 (“Remove the space between the cells with CSS”) rightly states:
table { border-collapse: collapse; }Rob (3 comments) ( 26 Mar 2008 )
I’m working on some table -based graphs at the moment and am styling them with CSS. Thanks for this article, it couldn’t have come at a better time.
Sharing Best Practices! (1 comments) ( 12 Apr 2008 )
I was looking for the gradient background stuff for custom WordPress theme, the client needs the theme colors to be changed anytime.
I am sure this is gonna help me a lot. Will give it a try.
Thanks for sharing..
Shafaat Awan (2 comments) ( 27 Aug 2008 )
For me, tables are not bad, Its better to use custom CCS layout instead of this, tables are good for tabular data. They are not built for structuring the layout.
Vincenzo Romano (1 comments) ( 3 Apr 2009 )
I’ve read Hixie’s interesting page.
But it’s still not clear why width or border properties are different from text-align!
Whatever the CSS mechanism does with the former ones, can be done for the latter. It sounds straightforward to my ears (but maybe I’m wrong).
In my opinion, it makes perfect sense to define table styles either by rows or by columns accordingly to the specific table.
In general, if you have items on the rows and their properties on the columns, styling by column makes better sense.
Your suggested workaround is … just a workaround. A working one, indeed.
But column styles should not rely on column ordering! And your solution does.
Emil Stenström (605 comments) ( 3 Apr 2009 )
@Vincenzo Romano: I agree that it’s not a perfect solution, but it’s the only one that works. I think hixie’s explaination simply is that width and border affects other cells in the table, so it you set column widths calculating table cell widths gets really hairy. That’s my guess anyhow.
Cody (13 comments) ( 20 May 2009 )
Hey thanks for the CSS table tips. There were a couple of techniques I never knew about. Like the table-layout: fixed; I always wonder how you can make tables obey your width element. Also great trick with the tag.