Adding style with CSS: a beautiful table

31 January 2009, in CSS, HTML | 8 comments »

I’ve always enjoyed styling tables. I’m a perfectionist when it comes to it and I just love the process of adding little bits of love and care to completely transform a dull and drab table into something fun, lively and pleasant to look at. This article will go into one of the diverse ways in which I style them and I hope it inspires you to make your own exciting tables.

Semantic markup

Here’s an example of a table that you’ve probably seen many times before. As always, we begin by wrapping up our content in some semantically correct markup. This way the table will make more sense to screen readers, as well as being easier for us to add some of the CSS pixie dust, without having to add unnecessary markup to it.

<table summary="Travel times to work by main mode (Autumn 2006)
    - Source: London Travel Report 2007
    http://www.tfl.gov.uk/assets/downloads/corporate/London-Travel-Report-2007-final.pdf">

	<caption>Travel patterns in London - Travel times to work by main mode (Autumn 2006) - Minutes</caption>

    <thead>
    	<tr>
            <th scope="col" rowspan="2">Main mode</th>

            <th scope="col" colspan="6">Area of workplace</th>
        </tr>

        <tr>
            <<th scope="col">Central London</th>

            th scope="col">Rest of Inner London</th>
            <th scope="col">Outer London</th>
            <th scope="col">All London</th>
            <th scope="col">Rest of Great Britain</th>

            <th scope="col">Great Britain</th>
        </tr>
    </thead>

    <tfoot>
    	<tr>

            <th scope="row">All modes</th>
            <td>55</td>
            <td>39</td>
            <td>27</td>

            <td>39</td>
            <td>20</td>
            <td>23</td>
        </tr>

    </tfoot>

    <tbody>
    	<tr>
    	    <th scope="row">Car and van</th>
            <td>48</td>

            <td>32</td>
            <td>25</td>
            <td>29</td>
            <td>20</td>

            <td>20</td>
        </tr>

        <tr>
            <th scope="row">Motorbike, moped, scooter</th>

            <td>36</td>
            <td>29</td>
            <td>27</td>
            <td>31</td>

            <td>19</td>
            <td>21</td>
        </tr>

        <tr>

            <th scope="row">Bicycle</th>
            <td>33</td>
            <td>24</td>
            <td>20</td>

            <td>25</td>
            <td>15</td>
            <td>17</td>
        </tr>

        <tr>
            <th scope="row">Bus and coach</th>
            <td>47</td>
            <td>39</td>

            <td>36</td>
            <td>40</td>
            <td>33</td>
            <td>34</td>

        </tr>

        <tr>
            <th scope="row">National Rail</th>
            <td>69</td>

            <td>66</td>
            <td>43</td>
            <td>66</td>
            <td>47</td>

            <td>58</td>>
        </tr>

        <tr
            <th scope="row">Underground, tram, light rail</th>
            <td>49</td>

            <td>45</td>
            <td>37</td>
            <td>47</td>
            <td>42</td>

            <td>46</td>
        </tr>

        <tr>
            <th scope="row">Walk</th>

            <td>21</td>
            <td>16</td>
            <td>13</td>
            <td>15</td>

            <td>12</td>
            <td>13</td>
        </tr>

    </tbody>

</table>

Breaking the markup down

It’s worth noting at this point that it’s a good idea to include the summary attribute and the caption tag in your tables, so people using screen readers know immediately what the table is about. Remember that you can only add the caption immediately after the table start tag.

You should use the thead, tbody and tfoot tags, to wrap the different type of content in a more semantic way. This will also make the table header and table foot printed in all pages, in tables that spread across more than one page. Note that you can only use one thead and tfoot per table, but you may have one or more tbody tags.

For each cell of our table, we either have a th or a td, depending if it’s a header or a simple data cell. Each row in our table is closed within tr tags – table row.

A th tag is an element that refers to a table header. These commands tell content in table cells to appear in header form; just like any header in a document. This makes it ideal for titles and other headers at the top of columns, etc.

In the th elements, we defined whether that header affects the row or the column of data by using the scope attribute. Also, because 2 of the th span across more than one row or column, we use the colspan and rowspan attributes to indicate how many rows or columns that element will span across.

The other tag that’s available for us to use is the td or table data tag. This differs from the th tag because it tells the content to just appear as a regular body of text without any specific formatting, such as: bold, italic or underlined. This makes it ideal for regular data cells.

The CSS

Now let’s make this table look better with some CSS goodness.

First we’ll deal with resetting margins and paddings and overriding the default bold font of the headers:

table, caption, td, tr, th {
	margin:0;
	padding:0;
	font-weight:normal;
	}

Second, we’ll define the width of the table, and make sure our cells have no spaces around them. We’ll also style the caption element, by aligning it to the left and setting the font size and padding:

table {
	border-collapse:collapse;
	margin-bottom:15px;
	width:90%;
	}

	caption {
		text-align:left;
		font-size:15px;
		padding-bottom:10px;
		}

Next step: let’s add some breathing space around our cells and define a little white bottom and right border for each. We already saw that all our data is either within a th or a td tag, so we’ll point to those in our stylesheet:

	table td,
	table th {
		padding:5px;
		border:1px solid #fff;
		border-width:0 1px 1px 0;
		}

Now we can start adding some details that will make our table easier to read. For example, let’s give a different colour for the th cells depending if they’re within the thead or the tbody, and then we’ll darken the ones with a colspan or rowspan attributes. This will only work in some browsers (because we’ll be using the attribute selector), but it will still look OK in less compliant ones.

	thead th {
		background:#91c5d4;
		}

		thead th[colspan],
		thead th[rowspan] {
			background:#66a9bd;
			}

	tbody th,
	tfoot th {
		text-align:left;
		background:#91c5d4;
		}

This is a very simple approach to the attribute selectors. Breaking it down:

thead th[colspan] { background:#66a9bd; }

We’re basically saying that for every th within the thead that has the colspan attribute defined, that is the background we want it to have. It will work independent of the value that we give to the attribute, as long as the element has it. We could have used it for any type of attribute, just using the following selector template:

selector[attribute] { property: value; }

For further reading on this subject, you can take a look at the links at the end of this post.

Going back to our table, we still have to take care of our td elements:

	tbody td,
	tfoot td {
		text-align:center;
		background:#d5eaf0;
		}

Because the last row represents the average commute time for all the modes, we’ll style it a bit differently:

	tfoot th {
		background:#b0cc7f;
		}

	tfoot td {
		background:#d7e1c5;
		font-weight:bold;
		}

Remember that in this case, we only have one table in our file, so these CSS selectors are very generic, but you can have more specific selectors, for example, if you only want to style a particular table within your website, or if you have different styles for different tables. You could do that by adding an id or a class to your table and specifying it within the CSS. For example:

table#travel {
	border-collapse:collapse;
	margin-bottom:15px;
	width:90%;
	}

	table#travel caption {
		text-align:left;
		font-size:15px;
		padding-bottom:10px;
		}

	table#travel table td,
	table#travel table th {
		padding:5px;
		border:1px solid #fff;
		border-width:0 1px 1px 0;
		}

	table#travel thead th {
		background:#91c5d4;
		}

Some jquery to the equation

Sometimes tables can become very long and hard to read. It’s not really our case, but it would still be helpful if we could add a different colour for when we’re hovering each data row, so we don’t have to move our fingers across the screen to guide us to the right header.

We could easily do this by adding a CSS pseudo class (:hover) to our tr elements, but that wouldn’t work in some less modern browsers, would it? And with a few simple “cut & paste” lines of jQuery we’ll make sure it works in browsers like Internet Explorer 6 and 7.

First, let’s create a new CSS style for when the trs are hovered over:

	tbody tr.odd td {
		background:#bcd9e1;
		}

We’ll later make sure that the jQuery adds the class “odd” to the hovered trs.

Second we’ll have to download the latest version of jQuery from its website and then link to it on our html file. Add the following code inside the head tags (and make sure to change the file paths to suit your needs):

<script type="text/javascript" src="js/jquery-1.2.6.min.js"></script>
<script type="text/javascript" src="js/style-table.js"></script>

I’m not putting the javascript code directly into the html file – like I’m not adding the CSS either -, because separating the content from the rest will make for a cleaner and lighter file, and, let’s not forget, easier to update!

So we’ll create a javascrip file and name it style-table.js. In that file we’ll paste the following lines of code:

$(document).ready(function () {

	$('tbody tr').hover(function() {
	  $(this).addClass('odd');
	}, function() {
	  $(this).removeClass('odd');
	});

});

Ignore the rest and focus on this part: (’tbody tr’). This is telling the script to look for a tr within the tbody. You could do something like: (’.mytable tr’) if you wanted it applied to a specific table, for example.

Then, the scrip will add the class “odd”: .addClass(’odd’). Again, you could name the class something different, like “hovered”, which would make the code look like this instead: .addClass(’hovered’). Pretty simple, right? :)

Conclusion

Like I said in the beginning, HTML tables don’t have to be boring at all. Personally I enjoy styling them because I can really add little details that will make them look so much better and easier to read, and that will improve the overall usability and experience of my websites.

I hope this simple tutorial may have shed a light onto the often ignored and avoided table and that you may have as much fun as I do working with them!

View example Download source files

Further reading

There are 8 comments:

  1. Very Useful and clear you girl are awesome

  2. Yaili says:

    Thanks! Glad I could help.

  3. pdziok says:

    Im using kinda same way to do the borders. All rest – amazing!

  4. Ahmed says:

    awesome work!
    Thanks

  5. Alex says:

    If you want more people to try your table I suggest to put an live example of how the table will look after the modification you have done. For example I want to see how is the table looking in final stage, to see if it’s worth to use it.

  6. Alex says:

    Never mind, I just so a small box on the site, where is saying view example. You should put an big example right on the web page. Ignore my previous comments.

  7. Peter says:

    This is very usefull, used these ideas on my current project and looks a whole lot better!

  8. I’ve recently used the nth-of-type selector to apply a very basic zebra striping, but never consider it’s use along with rgba to create a layering effect.

Leave a comment: