This article and demo come to us courtesy of Ivan Enderlin, author of the HOA Framework and longtime web developer.
This is the article that accompanies the demo below, showing the use of CSS3 selectors implemented in Firefox 3.5 for easy and stylish tables.
See this demo step by step.
Basic HTML Table
First, we start by writing a simple HTML table. Note: we do not have any class
es or id
s, which is what makes this all so fantastic:
... | ...... |
---|---|
... | ...... |
... | ...... |
And now, let us write some CSS to make the plain old table look a bit more stylish:
table {
font: 90%/1.5em "Lucida Grande", Geneva,
"DejaVu Sans", "Bitstream Vera Sans", AnjaliOldLipi,
"Lucida sans", "Trebuchet MS", Arial, Verdana;
text-align: center;
border: 4px black double;
border-spacing: 0;
-moz-border-radius: 12px;
-moz-box-shadow: #6a3d37 5px 5px 6px;
-webkit-border-radius: 12px;
-webkit-box-shadow: #6a3d37 5px 5px 6px;
border-radius: 12px;
box-shadow: #6a3d37 5px 5px 6px;
background: #b59d5c
}
The use of border-spacing, border-radius
and box-shadow
properties make for a quick and easy way to inject a little beauty into the table.
First Selection
Now, we would like to style all the th
tags. This is easy with CSS Selectors:
th {
color: #fff;
font-size: 110%;
text-shadow: #6a3d37 2px 2px 2px
}
Reminder: if we write table th
we intend to select all the th
elements which are child elements of the the table element, and if we write thead > th
, we intend to select all the th
elements which are direct children of the thead
element. Well, it was just a reminder :-)
More Nuanced Selection
The th
tag represents a table header. We would like to select the first table header. Hmm… maybe we should use the first-of-type
pseudo-class. It represents an element that is the first sibling of its type in the list of children of its parent element. So now we have:
th:first-of-type {
font-weight: bold;
font-style: italic
}
Even and odd rows
A recurrent problem with tables is: how to select even and odd rows? The solution is the nth-child() pseudo-class. All these pseudo-classes understand the an+b
syntax — to select all the even elements, we use 2n; to select all the odd elements, we use the 2n+1 elements; to select all third elements, we use 3n. In other words, this matches the bth
child of an element after all the children have been split into groups of a
elements each.
So, let’s style the even and odd rows:
tr:nth-child(odd) {
color: #e0d8cb;
background: #474644
}
tr:nth-child(even) {
color: #6a3d37
}
Padding on first and last columns
Now, we want to add a padding to the first and the last column. I remind you again that we do not have any classes or IDs, and that the number of columns is unknown.
The solution is the first-of-type
and the last-of-type
pseudo-classes. We select all the first and last th
and td
like this:
th:first-of-type,
td:first-of-type {
padding: 0 0 0 4em
}
th:last-of-type,
td:last-of-type {
padding: 0 4em 0 0
}
The two last rows
Now, we would like to combine many pseudo-classes (and introduce a new one).
Let’s say we would like to select row number 1, number 4 and number 7. The mathematical expression is not so simple as we hoped. The tips is to split our rows in groups of 3, like this: 3n. But, that will select rows number 3, 6 and 9. Almost there! In these groups, we will select the first element, so 3n+1 (or 3n-2 if you like to complicate things).
That’s good, but that will select a row in our two last non-opaque rows. Ideally, we should say: “select the first row of each groups of three rows, but not the last row (which will be selected, because the last is the 7th row).” Simple. We are going to use the not
pseudo-class, combined with the last-child
pseudo-class (or last-of-type
, which also works here).
Thus:
tr:nth-last-child(-n+2) {
opacity: .75
}
tr:nth-child(3n+1):not(:last-child) td {
text-shadow: red 0 0 8px
}
The final source is:
table {
display: table;
font: 90%/1.5em "Lucida Grande", Geneva,
"DejaVu Sans", "Bitstream Vera Sans", AnjaliOldLipi,
"Lucida sans", "Trebuchet MS", Arial, Verdana;
text-align: center;
border: 4px black double;
border-spacing: 0;
-moz-border-radius: 12px;
-moz-box-shadow: #6a3d37 5px 5px 6px;
-webkit-border-radius: 12px;
-webkit-box-shadow: #6a3d37 5px 5px 6px;
border-radius: 12px;
box-shadow: #6a3d37 5px 5px 6px;
background: #b59d5c
}
th {
color: #fff;
font-size: 110%;
text-shadow: #6a3d37 2px 2px 2px
}
th:first-of-type {
font-weight: bold;
font-style: italic
}
tr:nth-child(odd) {
color: #e0d8cb;
background: #474644
}
tr:nth-child(even) {
color: #6a3d37
}
th:first-of-type,
td:first-of-type {
padding: 0 0 0 4em
}
th:last-of-type,
td:last-of-type {
padding: 0 4em 0 0
}
tr:nth-last-child(-n+2) {
opacity: .75
}
tr:nth-child(3n+1):not(:last-child) td {
text-shadow: red 0 0 8px
}
10 comments