Apps

CSS3 styling for data tables

Ryan Boudreaux demonstrates some of the styling for data tables that is possible with new CSS3 code. Here are two examples of code, along with explanation of the properties.

One of the nice options with CSS3 is the ability to assign tbody styling to table rows and columns; you can also specify either even or odd rows using the nth-child property, which will be demonstrated in the second example. This is a boon for styling tables of data which typically would require either manual color coding for alternate rows or utilizing table formatting features in text editors such as Dreamweaver, which assign styling directly to the HTML. Creating styling rules in your CSS allows greater options for various types of table presentations.

For this demonstration we will use static data, and this will be the base table structure for use in both examples; however, data from dynamic database sources would work just as easily:

<table class="table_2" summary="Wholesale and retail and prices for popular produce at several farmers markets">
    <caption>
    <strong>Wholesale and retail prices for popular produce at several farmers markets</strong>
    </caption>
       <thead>
               <tr>
                     <th scope="row">Local Fresh</th>
                     <th scope="col" abbr="Beets">Beets</th>
                     <th scope="col" abbr="Broccoli">Broccoli</th>
                     <th scope="col" abbr="Carrots">Carrots</th>
                     <th scope="col" abbr="Leaf Lettuce">Leaf Lettuce</th>
                            <th scope="col" abbr="Radish">Radish</th>
                     <th scope="col" abbr="Tomatoes">Tomatoes</th>
               </tr>
       </thead>
       <tfoot>
       <tr>
               <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
        </tr>
               <tr>
                     <th scope="row">Avg Discount</th>
                     <td>$ .75</td>
                     <td>$ .90</td>
                     <td>$ .90</td>
                     <td>$ .85</td>
            <td>$ .90</td>
            <td>$ .90</td>
               </tr>
       </tfoot>
       <tbody>
               <tr>
                     <th scope="row">Wholesale</th>
                     <td>$ .75</td>
                     <td>$ .85</td>
                     <td>$ .30</td>
                     <td>$ .95</td>
            <td>$ .65</td>
            <td>$ 1.25</td>
               </tr>
               <tr>
                     <th scope="row">Retail</th>
                     <td>$1.50</td>
                     <td>$ 1.45</td>
                     <td>$ .85</td>
                     <td>$ 1.95</td>
            <td>$ 1.35</td>
            <td>$ 2.65</td>
               </tr>
               <tr>
                     <th scope="row">Discounts</th>
                       <td><span class="check"></span></td>
                       <td><span class="check"></span></td>
                       <td><span class="check"></span></td>
                       <td><span class="check"></span></td>
            <td><span class="check"></span></td>
            <td>&nbsp;</td>
         </tr>
      <tr>
               <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
      </tr>
      <tr>
       <thead>
               <tr>
                   <th scope="row">Regional Fresh</th>
                   <th scope="col" abbr="Beets">Beets</th>
                   <th scope="col" abbr="Broccoli">Broccoli</th>
                   <th scope="col" abbr="Carrots">Carrots</th>
                   <th scope="col" abbr="Leaf Lettuce">Leaf Lettuce</th>
                   <th scope="col" abbr="Radish">Radish</th>
                          <th scope="col" abbr="Tomatoes">Tomatoes</th>
               </tr>
        </thead>
               </tr>
               <tr>
                      <th scope="row">Wholesale</th>
                      <td>$ .70</td>
                      <td>$ .82</td>
                      <td>$ .27</td>
                      <td>$ .88</td>
                      <td>$ .62</td>
                      <td>$ 1.18</td>
               </tr>
               <tr>
                     <th scope="row">Retail</th>
                     <td>$ 1.40</td>
                     <td>$ 1.35</td>
                     <td>$ .75</td>
                     <td>$ 1.75</td>
            <td>$ 1.25</td>
            <td>$ 2.25</td>
               </tr>
               <tr>
                       <th scope="row">Discounts</th>
                       <td><span class="check"></span></td>
                       <td><span class="check"></span></td>
                       <td><span class="check"></span></td>
                       <td>&nbsp;</td>
                       <td><span class="check"></span></td>
                            <td><span class="check"></span></td>
               </tr>
       </tbody>
</table>

I have also added a few accessibility items to the table (i.e., the summary and caption) however, this piece will concentrate more on CSS3 functionality than accessibility, which will be a topic for another post.

In this example, we have all the elements that a typical data table needs, including a header, a body, and footer. In this tutorial, we will use several fresh produce market price comparisons which include popular vegetables for the table. The following two styles can be applied to this table by changing the class to table_1, and table_2.

Blue Gradient Table Color Scheme (Table 1)

The first table will be styled in blue color tones with some gradients for the descriptive cells and the "th" elements. In order for the table to have a small space between the cells, I've added the border-collapse separate property as you see below.

table.table_1{
    font-family: Cambria, serif;
    font-size: 17px;
    font-weight: normal;
    line-height: 1.4em;
    font-style: normal;
    text-transform: normal;
    border-collapse: separate;
}

In the styling for the head "th" elements, I've added a background with three gradient styling colors with rgb color stops for -webkit- and rgb percents for -moz- prefixes; I added a rounded border radius for the top left and top right corners, along with a modest 5px padding to keep the contents well spaced, and then added a solid bottom border color with a height of 3 pixels.

.table_1 th{
    padding:5px;
    color:#fff;
    text-shadow:1px 1px 1px #3B4545;
    border:1px solid #3799CE;
    border-bottom:3px solid #6B81B1;
    background-color:#2B4478;
    background:
       -webkit-gradient(linear, left bottom, left top,
        color-stop(0.02, rgb(13,33,76)),
        color-stop(0.51, rgb(87,116,177)),
        color-stop(0.87, rgb(107,129,177))
        );
    background:
       -moz-linear-gradient(center bottom,
        rgb(13,33,76) 2%,
        rgb(87,116,177) 51%,
        rgb(107,129,177) 87%
        );
    -webkit-border-top-left-radius:5px;
    -webkit-border-top-right-radius:5px;
    -moz-border-radius:5px 5px 0px 0px;
    border-top-left-radius:5px;
    border-top-right-radius:5px;
}

Next, we need to address the empty "th" sections of the table. With CSS3, we are allowed to select an empty "th" and apply styling to it, as in this example:

.table_1 th:empty{
    background:transparent;
    border:none;
}

For the table footer "td" the font will be 20px, aligned center, with a 1px text shadow for a standout effect, padding of 5px and 10px, a slightly darker blue background, border radius of 3px on all corners, and for the footer, "th" the font color will be a light tan hue:

.table_1 tfoot td{
    color: #D4B476;
    font-size:20px;
    text-align:center;
    padding:5px 10px;
    text-shadow:1px 1px 1px #3B352B;
    background-color:#6B81B1;
    -moz-border-radius:3px;
    -webkit-border-radius:3px;
}
.table_1 tfoot th{
    color:#D4B476;

}

The inner cells with the pricing data content will have a light blue background with a light text shadow for another standout effect, a 2px border and rounded 2px radius on all corners, which will create a shadow effect:

.table_1 tbody td{
    padding:10px;
    text-align:center;
    background-color:#CAE2F3;
    border: 2px solid #E0E6EF;
    -moz-border-radius:2px;
    -webkit-border-radius:2px;
    border-radius:2px;
    color:#666;
    text-shadow:1px 1px 1px #fff;
}

And to indicate which vegetables can be discounted at each market, I've added a span with a "check" class, i.e.,<span class="check"></span> to all the cells for vegetables that would be indicated with a discount. This styling property allows the addition of specific content such as the check mark image in this example, and the ::before or ::after indication stipulates where it is inserted -- either before or after other content contained within the element -- this is all represented with the following CSS to call the style:

.table_1 tbody span.check::before{
    content : url(images/Check_01.png)
}
The blue gradient background table is displayed in Figure A below as displayed in Firefox 7.0.1:

Alternating Rows Ivory and Red Color Scheme (Table 2)

For the second example, I will add in styling for alternating row color effects. In addition to the nth-child property which is displayed toward the bottom of this example, I have also updated several of the styles from the first example.

For the base table style, I've changed the font family to Courier New, the size to 18px, and the border collapse to collapse so that there will be little space between cells. All stylings in this example are referenced by changing the class to "table_2".

table.table_2{
    font-family:"Courier New", Courier;
    font-size: 18px;
    font-weight: normal;
    line-height: 1.2em;
    font-style: normal;
    text-transform: normal;
    border-collapse: collapse;
}

The table "th" has been updated also with new colors for the gradient, and borders representing several shades of and ivory color scheme.

.table_2 th{
    padding:5px;
    color:#fff;
    text-shadow:1px 1px 1px #999481;
    border:1px solid #D7D5CE;
    border-bottom:3px solid #D7D5CE;
    background-color:#2B4478;
    background:
        -webkit-gradient(linear, left bottom, left top,
        color-stop(0.02, rgb(153,148,129)),
        color-stop(0.51, rgb(215,213,206)),
        color-stop(0.87, rgb(248,248,248))
        );
    background:
        -moz-linear-gradient(center bottom,
        rgb(153,148,129) 2%,
        rgb(215,213,206) 51%,
        rgb(248,248,248) 87%
        );
    -webkit-border-top-left-radius:5px;
    -webkit-border-top-right-radius:5px;
    -moz-border-radius:5px 5px 0px 0px;
    border-top-left-radius:5px;
    border-top-right-radius:5px;
}

The empty "th" styling again:

.table_2 th:empty{
    background:transparent;
    border:none;
}

Below are the tfoot "td" and "th" styles with an updated color for contents, text-shadow, and background color:

.table_2 tfoot td{
    color: #D4B476;
    font-size:22px;
    text-align:center;
    padding:5px 10px;
    text-shadow:1px 1px 1px #999481;
       background-color:#D7D5CE;
}
.table_2 tfoot th{
    color:#D4B476;
}

The tbody "td" style with an updated text-shadow and the border radius styles omitted:

.table_2 tbody td{
    padding:5px;
    text-align:center;
    color:#666;
    text-shadow:1px 1px 1px #5E553E;
}

And the check images span styling for this example:

.table_2 tbody span.check::before{
    content: url(images/check_2.png);
}

Now, for the alternating rows continuing in the ivory color scheme with these CSS3 styles, note the use of nth-child(odd) and nth-child(even):

.table_2 tbody td {
       background:rgb(176,172,158);
       padding-top:4px;
}
.table_2 tbody tr:nth-child(odd) td {
       background:rgb(153,148,129);
       color:rgb(248,248,248);
}
.table_2 tr:nth-child(even) td {
       background::rgb(215,213,206);
       color:rgb(51,51,51);
}

With this styling the alternating even and odd rows will reset with each "thead", and will continue throughout the remainder of that table section only.

The resulting table with the ivory and red color scheme is displayed in Figure B below as displayed in Firefox 7.0.1:

There are many ways that data tables can be styled with CSS3, allowing unlimited options for your web sites data display designs. The source code and associated CSS and image files are available for download and are best viewed in Firefox (unzip files to a folder and click the HTML file).

About

Ryan has performed in a broad range of technology support roles for electric-generation utilities, including nuclear power plants, and for the telecommunications industry. He has worked in web development for the restaurant industry and the Federal g...

2 comments
jeffrey.bollman
jeffrey.bollman

[Quote marks this time...] According to the validator.w3.org it appears the following are invalid in html5: 1. "summary" (in a table element), (Line 18, Column 115:) 2. "abbr" (in a th element), (first occurrence: Line 23, Column 32:) 3. "br" is invalid (in an open "hgroup"), (Line 128, Column 6:) 4. Only 6 "th"s in one of the table rows.(Line 86, Column 11: A table row was 6 columns wide, which is less than the column count established by the first row (7).) 5. "Align" attribute on hr invalid (Line 129, Column 34:) 6. "hr" not allowed where it has been placed (in an open "hgroup") (Line 129, Column 34:) 7. (Line 207, Column 14: A table row was 0 columns wide) 8. Line 207, Column 14: Row 5 of a row group established by a tbody element has no cells beginning on it. 9. Line 218, Column 7: Stray end tag "tr". (relates to the empty referenced "tr" at Line 207). 10. Line 10, Column 16: Unclosed element "hgroup". 11. The element "thead" appears twice in table_2. This doesn't appear to be valid either. http://dev.w3.org/html5/spec/Overview.html#tabular-data 12. The "width" attribute in the "hr" appears to be invalid.(Line 129, Column 34: The width attribute on the hr element is obsolete.)

jeffrey.bollman
jeffrey.bollman

I tried your sample code. The tables look very interesting. I like the "blue gradient" styling. When I validated the code as downloaded, I ran into a few problems... {Result: 37 Errors, 5 warning(s) } (only first instance/s are identified below): I understand being under a deadline to finish an assignment, however, a quick validation of the code presented would be helpful. According to the validator.w3.org it appears the following are invalid in html5: 1. summary (in a table element), (Line 18, Column 115:) 2. abbr (in a th element), (first occurrence: Line 23, Column 32:) 3. is invalid (in an open ), (Line 128, Column 6:) 4. Only 6 in one of the table rows.(Line 86, Column 11: A table row was 6 columns wide, which is less than the column count established by the first row (7).) 5. Align attribute on hr invalid (Line 129, Column 34:) 6. not allowed where it has been placed (in an open ) (Line 129, Column 34:) 7. (Line 207, Column 14: A table row was 0 columns wide) 8. Line 207, Column 14: Row 5 of a row group established by a tbody element has no cells beginning on it. 9. Line 218, Column 7: Stray end tag tr. (relates to the empty referenced at Line 207). 10. Line 10, Column 16: Unclosed element hgroup. 11. The element appears twice in table_2. this doesn't appear to be valid either. 12 width attribute on appears to be invalid.