CSS tables are not difficult to stylize, provided that we properly understand how the table layout of CSS works. Tables and all their elements have a different display role in the CSS model. A table has table
as its display value, though it apparently seems to be rendered as a block-level element (it creates a new line in the document flow). However, a table doesn't behave as a normal block-level element, because it can actually resize or increase its dimensions according to the content hosted inside it. In the CSS table model, a row determines the actual size of a table. In other words, the more content you insert in a row (say, more cells), the more its dimensions will be augmented. This is called row supremacy in the CSS specifications. Within a row there are also columns. The final width of a column will be determined by the widest table cell inside of it by default. As we can see, this behavior can be changed in our CSS. Now, let's start with a basic table that contains a caption, three table headers, three more rows and nine cells:
<table summary="Sample table"> <caption>Sample table</caption> <tr> <th scope="col">Header A</th> <th scope="col">Header B</th> <th scope="col">Header C</th> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> </tr> <tr> <td>Data</td> <td>Data</td> <td>Data</td> </tr> </table>
A table can have a summary
attribute. This is a good aid for accessibility, because it describes the content that will be read aloud. A caption comes always before any table row and it's displayed outside the main content of the table. Table headers can have a scope
attribute that tells browser if they're related to a column (col
) or a row (row
). Now let's start stylizing this table.
Global table styles
Global table styles will affect the appearance of the table
element. More specifically:
- dimensions (
width
) - default layout algorithm (
table-layout
) - border collapsing (
border-collapse
) - border spacing (
border-spacing
)
These properties will also have an effect on table elements, more specifically table cells (th
, td
). Let's see our styles:
table { width: 33em; table-layout: fixed; background: #666; color: #fff; border-collapse: separate; border: 2px solid #999; -moz-border-radius: 6px; border-radius: 6px; font-size: 1.3em; border-spacing: 0; }
The table layout is set to fixed
(defaults to auto
). This allows browsers to calculate and render the table layout a lot faster. Since we want to use the CSS3 border-radius
property, the border-collapse
property must be set to separate
(that's the default value, the other is collapse
). This property tells browsers if table borders must be rendered as continuous or separated. In this case, we don't want to see a gap between table cells, so we zero border spacing by using the border-spacing
property. border-spacing
can accept up to two values: if both are specified, the former refers to horizontal spacing, while the latter refers to vertical spacing. Negative values are not allowed.
Caption styles
Caption styles are very simple:
caption { color: #666; font: 1.5em Georgia, serif; text-align: center; padding-bottom: 4px; text-transform: uppercase; letter-spacing: 0.1em; }
Bear in mind, however, that a caption is not a block-level element. If you want, say, to apply a solid background color to it, you must first turn it into a block-level element. If you don't do so, you will probably see that the element's background don't stretch to cover the entire width of the table.
Cell styles
Cells require a little more work to handle the vertical alignment of text:
th { text-align: left; font-weight: bold; background: #ea9329; color: #fff; padding: 0.3em; font-variant: small-caps; vertical-align: middle; } td { padding: 0.3em; vertical-align: middle; }
We use the vertical-align
property to vertically align the text of these elements just in the middle. By default, text is aligned to the baseline. Further, since table headers have their text horizontally centered by default, we set the text-align
property to left
.
Alternate rows
With CSS3 selectors, you could easily get the effect of alternate rows just with this single rule:
tr:nth-child(even) { background: #fae381; color: #000; }
IE8 and lower versions don't support this kind of selectors, so we're forced to use JavaScript (sigh!) to get the desired result:
function makeAlternateRows(type, klass) { type = type || 'odd'; var tr = document.getElementsByTagName('tr'); var i, len = tr.length; for(i = 0; i < len; i += 1) { if(type == 'odd') { if(i % 2 == 1) { tr[i].className = klass; } } else { if(i % 2 == 0) { tr[i].className = klass; } } } } window.onload = function() { makeAlternateRows('even', 'alternate'); }
Using the modulus operator, we can actually add a CSS class to even or odd table rows.