Mozilla

slick tables with css 3 selectors

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.

CSS3 Selectors for Quick and Pretty Tables

View the Demo | CSS3 Selectors for Quick and Pretty 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 classes or ids, which is what makes this all so fantastic:

<table>
  <thead>
    <th>...</th>
    ...
    <th>...</th>
  </thead>
  <tbody>
    <tr>
      <td>...</td>
      ...
      <td>...</td>
    <tr>
    ...
    <tr>
      <td>...</td>
      ...
      <td>...</td>
    <tr>
  </tbody>
</table>

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
}


View this demo step by step
.

10 comments

Comments are now closed.

  1. Jeff Walden wrote on July 7th, 2009 at 02:16:

    Typo again: in your “Padding on first and last columns” paragraph, the first padding property should be “0 0 0 4em” (top right bottom left, of course), not the top as you have with “0 0 4em 0″. The actual CSS doesn’t have this error (nor does the final source displayed in the post), hence no visual glitch.

  2. Daniel Glazman wrote on July 7th, 2009 at 02:46:

    Typo in “More nuanced selection” section: “th: first-of-type” instead of “th:first-of-type”

  3. Ivan Enderlin wrote on July 7th, 2009 at 03:50:

    @Jeff : My bad. I corrected it on my article (but Eric should correct it on the blog post).

    @Eric : You have missed my penultimate section. Here it is: http://mozilla.hoa-project.net/Demo/Css_3_selectors/Article.html

  4. Arun Ranganathan wrote on July 7th, 2009 at 08:43:

    @Jeff, @Daniel: Typos fixed — thanks for your vigilance :)

  5. Arun Ranganathan wrote on July 7th, 2009 at 18:09:

    @Ivan — thanks for contributing to hacks.mozilla.org :) If you look at your article, two sections (“The last two rows…” and “Headache ensured…”) are identical. Am I missing something?

  6. Jack wrote on July 8th, 2009 at 03:09:

    Please don’t put “DejaVu Sans”, “Bitstream Vera Sans” in front of Trebuchet and Arial. Those Linux fonts are crappy, and Windows users shouldn’t have to withstand them! (they are installed with some applications on Windows).

  7. Ivan Enderlin wrote on July 8th, 2009 at 04:07:

    @Arun : Oops, you’re right. I have updated my article :-).

  8. Ivan Enderlin wrote on July 11th, 2009 at 00:00:

    I have updated my article: I forgot a tag around ones. It involves a little modification in my CSS (sometimes, adding a tbody in CSS selectors). Nothing really important.

  9. Komrade Killjoy wrote on July 28th, 2010 at 05:49:

    maybe CSS selector “feature” in ABP element hiding helper will become less clunky soon

  10. Pingback from jQuery ui-datepickers calendar table width overflows ui-datepicker(Resolved) - Tech Forum Network on February 21st, 2012 at 17:17:

    […] http://hacks.mozilla.org/2009/07/slick-tables-with-css-3-selectors/ […]

Comments are closed for this article.