Section 1: Overview
Tables, when processed by CSS, conform to a complicated set of algorithms referred to in the CSS specification as the CSS table model.
- The CSS table model defines special display characteristics for each of the elements within a table.
Display Properties
A handful of CSS display property values exist that apply specifically to tables. The list of these property values includes:
- table
- inline-table
- table-header-group
- table-row-group
- table-footer-group
- table-row
- table-cell
- table-column
- table-column-group
- table-caption
Section 2: Centering Tables
The most common way of centering a table is to set the margins to auto, like this:
table.center
{
margin-left:auto;
margin-right:auto;
}
<table class="center">
. . .
</table>
For more details on centering tables, visit this link.
Section 3: Table Styling (including borders)
We learned about borders, margins, and padding, all of which apply to formatting tables, in the CSS3 Box Model discussion.
There are several attributes that have been "obsoleted" with the advent of HTML5.
A series of examples will demonstrate how tables should now be formatted using CSS. Here is a basic table with no formatting:
Here is the same table with some formatting applied. It can also be viewed here.
Here is the CSS for the example above:
table
{
width: 600px;
font-size: 14px;
font-family: Helvetica, Arial, sans-serif;
border-collapse: separate;
border-spacing: 10px 5px;
table-layout: auto;
empty-cells: show;
}
The border-collapse Property
The border-collapse table property determines the table's border model.
-
Possible values for this property are collapse, separate, and the
cascaded value inherit.
- Supplying a value of collapse will trigger the table's collapsing border model, wherein the spacing between cells is collapsed and the browser re-calculates any border property applied to table cells and headings.
- Declaring border-collapse: separate – as in the code above – triggers the separated borders model, wherein each table cell is spaced apart from its neighboring cells.
This example shows the effect ot border-collapse:collapse. It can also be viewed here.
The border-spacing Property
The border-spacing table property controls the amount of separation between the borders of adjacent cells.

-
The property can accept one or two length values (or a value of inherit).
- If one value is present, then cells are spaced apart evenly using that value around all four sides of the cell.
- If two values are supplied, the first value represents the horizontal spacing between adjacent cells in the same row and the second value represents the vertical spacing between rows.
- While there is no official default value for this property, most browsers will add two pixels of spacing between cells if the border-spacing property is not explicitly set.
- The border-spacing property only applies to tables with the border-collapse property set to "separate".
The table-layout Property
The table-layout table property determines which layout algorithm a browser should employ as it renders the table.
-
Possible values are fixed, auto, and inherit.
- Using a property value of fixed triggers the fixed table layout algorithm which relies only on the table's overall width—supplied in CSS or inferred from the width of the table's content—and divides the width equally amongst all columns.
- The auto property value takes into account the overall width of the table, the contents of each of the table's cells, and any specified cell or column widths and divides width among columns as determined by the browser's own algorithm.
-
Browsers will render tables using table-layout: auto by default.
- This value triggers a more complex layout algorithm that requires the browser to first load the entire contents of the table and scan over every cell, generating a record of each cell's width.
- The table's layout is then determined based on the browser's findings.
The empty-cells Property
The empty-cells table property tells the browser whether or not to render styling on cells that have no content.
- Possible values for this property are show, hide, and inherit.
- By default, most browsers supposedly opt for the "show" value, so even empty cells will appear with whatever borders or background they would have if they carried content.
Padding
If you want some spacing within table cells, you must apply the padding property to each cell.
td, th
{
padding:5px;
}
Here are some tables to download and play with.
Section 4: Styling Columns
Styling tables from a column-based approach is a bit more complicated, with fewer options available.
Here is a sample table, without borders on cells, no background colors on even rows, and no empty-cells rule.
The following table can also be seen here.
Note that the #quantities column is set to 200 pixels in width and the cells in the #prices column are set to have a background color of #ddd.
Note especially the use of the <col> tag to specify specific formatting for table columns, and see this link for more details.
In addition, the cells in the thead and tfoot portion of the table retain their background color of #eee due to the influence of table layer stacking.
Stacking
As it pertains to determining a table cell's background color, there are six layers of stacking. (Assume for a moment that each of the following six layers has a unique background color specified on one of its elements.)
- The lowest layer, the table element itself.
- Column groups (override the table element).
- Individual columns (override column groups).
- Row groups (override individual columns).
- Individual rows (override row groups).
- Cell, the finest granularity and king of the hill!

The diagram shows how, looking down on the six rectangles, one may compute the background color of each cell. On the top layer, each cell that specifies a background is shown as a gray box with a black border. A cell without a background color in the top layer is depicted as a "window" onto the lower layers, which give its final background color. The same visual metaphor is used at each layer, so a row without a background acts as a window onto the row group layer, etc.
In the example code, cells – in this case, headings in the header and cells in the footer – beat out the background color declaration on the column.
- This is a rare case in which CSS specificity takes a back seat to stack order.
- The column's ID selector should overpower the cell's generic element selector, but the table layer model tells the browser to give preference to stacking order over specificity.
Section 5: Structural Pseudo-Classes
The structural pseudo-classes are especially useful for formatting tables.
- These classes let you select elements by their structural location.
- Using these pseudo-classes in selectors helps to avoid the use of id and class selectors, which simplifies your HTML.
The first example shows the use of :last-child for a thicker border at the foot of the table:
If you look at the CSS you'll notice the following two declarations:
tfoot:last-child
{
border-bottom:thick solid black;
}
The :last-child selects last child element under the parent element, in this case the tfoot.
With reference to the original example (repeated below)...
If you look at the CSS you'll notice the following two declarations:
thead th:first-child
{
text-align: left;
}
tbody tr:nth-child( even )
{
background: #ddd;
}
The :first-child and :nth-child pseudo-classes are structural pseudo-classes that select elements based on where they occur in the markup.
-
The :first-child pseudo-class left-aligns the text of
the table heading that is a first-child descendant of the
table heading.
- More generally, the :first-child pseudo-class refers to an element that is the first child of another element such as the first li in an unordered list or the first paragraph in an article.
-
The :nth-child pseudo-class matches an element or set of
elements based on the keyword or formula passed to it in
parenthesis.
- In the example above, only even-numbered rows are matched by the selector.
- A look back at the formatted table shows that the second table row in the body of the table has a background color.
- The keywords 'even' and 'odd' are equivalent to the formulas 2n and 2n+1, respectively.
- Older browsers may not support these selectors.
Syntax | Description |
---|---|
:first-child | selects first child element under the parent element |
:last-child | selects last child element under the parent element |
:first-of-type | selects first child element of its type under the parent element |
:last-of-type | selects last child element of its type under the parent element |
Syntax | Description |
---|---|
:nth-child(n) | nth child of parent |
:nth-last-child(n) | nth child of parent counting backwards |
:nth-of-type(n) | nth element of its type within the parent |
:nth-last-of-type(n) | nth element of its type counting backwards |
Value | Meaning |
---|---|
odd | Every odd child or element |
even | Every even child or element |
n | The nth child or element |
2n | Same as even |
3n | Every third child or element (3,6,9,...) |
2n+1 | Same as odd |
3n+1 | Every third child or element starting with 1 (1,4,7,...) |
For additional types of structural pseudo class, visit the following links:
- CSS3: Structural Pseudo-Class Patterns
- CSS Pseudo class selectors explained with example, DOM tree and cheat sheet
So what good are structural pseudo classes? Here are some examples.
Let's look again at the table in the previous section (link):
After widening the Quantity column (column 2), the table might look better if that column was right justified.
- We used a <colgroup> and a <col> with the id "quantities", and the CSS for that id set the column width to 200 px.
- Following that logic, we can also specify text-align:right; for that id. If you try it, you see no change in the column width.
- In fact, no matter what you try you have to specify text-align:right; for every individual cell or <td> in that column! Unless...
- This is where the structural pseudo classes come in handy:
/*
The above CSS provides the formatting that we wanted.
right aligns the 2nd column in the table
*/
tbody td:nth-child(2)
{
text-align: right;
} - If you wanted to right align both the Quantity (column 2) and the
Totals (columns 4) columns, you could specify this in the CSS:
/*
Because "even" will be applied to the second, fourth, and even sixth column (if one existed).
right aligns even numbered columns
*/
tbody td:nth-child(even)
{
text-align: right;
} - If you wanted to right align the Price column (column 3) and display
prices in a red font, you could use the following:
/*
right aligns column 3 with red font
*/
tbody td:nth-child(3)
{
text-align: right;
color: red;
}
Here is the result:
Note that the cells in the header and footer were not affected by the formatting.
The next example is based on the following table (link).
This table uses the following CSS:
/*
left-aligns the first column, including the header cells <th>,
the column cells <td>, and the footer cells <td>
*/
th:first-child, td:first-child
{
text-align: left;
}
/*
centers the second column, including the header cells <th>,
the column cells <td>, and the footer cells <td>
*/
th:nth-child(2), td:nth-child(2)
{
text-align: center;
}
/*
sets the background color of even numbered rows <tr> to
to silver
*/
tbody tr:nth-child(even)
{
background-color: silver;
}
Here are some links that explain CSS3 structural pseudo-classes in more detail:
Section 6: Styling Captions
The caption element, as you saw earlier, will generally appear above its parent table element.
- Its position is determined by the caption-side property.
- The following code shows how easy it is to style a table's caption.
The following table can also be seen here.
The caption-side property accepts one of three possible values: top, bottom, and inherit.
- As most browsers default to a value of top, you can safely leave out the caption-side declaration if you prefer to let your table captions ride high.
- If, however, you want to reposition your table captions, simply supply the caption-side property with a value of bottom and the caption moves visually below the table.
- Remember: regardless of the visual position of the table caption, the caption element must always be the first child of its parent table element.
Section 7: CSS Tables
Note that this is not CSS for HTML tables, but CSS tables.
Section 8: Let's Play
Click the "Edit and Click Me >>" to see the results of the html code in the left panel in the panel on the right.
Then, play around with the html code, making changes and seeing the effect of those changes in the right panel.