TitleJapanese TitleYear of ReleaseRun Time
Rashomon羅生門195088 minutes
IkuruI生きる1952143 minutes
Seven Samurai七人の侍1954207 minutes
Throne of Blood蜘蛛巣城1957105 minutes
The Hidden Fortress隠し砦の三悪人1958139 minutes
Yojimbo用心棒1961110 minutes
Ran1985160 minutes
Hover to highlight rows, click on table headers to highlight columns

The demarcation between the appropriate roles for , JavaScript and in modern web development can be a grey area. Perhaps one of the easiest ways to make this distinction clear is with tables. For example, in the table to the left, we want to accomplish several goals:

  • A background image that automatically resizes as we add and remove table data
  • Alternate appearance of table rows, to make them clearer
  • Highlight the row that the user places their cursor in
  • Make it clear which column our user is interested in.

All of this is just CSS. I've touched on almost all of the techniques I'm about to use in past articles, and will reference them as I go; the parts that are new and interesting are under-utilized and almost unknown tags that we'll use as markup to add more semantic "hooks" for our CSS to modify: <col />, <thead> and <tbody>.

Extended Table Markup

The code for our table looks something like this:

<table id="kurosawa">
	<caption>The Masterworks of Akira Kurosawa</caption>
			<th>Year of Release
			<th>Run Time
			<td>88 minutes
			<td>143 minutes
			<td>Seven Samurai
			<td>207 minutes

<thead> and <tbody> are fairly straightforward: they make clear what in the table is data versus header sections (<tfooter> is also possible). The <caption> tag is used for accessibility. What's new here is col.


When we construct HTML tables, we do so by row, creating table cells each row. Columns are implied, but they are not explicit. <col> is a reference to make that association clear: each <col> tag refers to the column of cells immediately below it when the table is rendered in the browser. Therefore, you would normally have the same number of cols declared as you have <td> cells in each row, as we do here.

It's possible to have a <col> take responsibility for multiple columns by using the span attribute: <col span="2">, for example).

Table Customisation

First, some base CSS:

table#kurosawa {
	background-size: cover;
	border-collapse: collapse;
table#kurosawa caption {
	font-size: larger;
	padding: 1em;
table#kurosawa td {
	padding: .5em;
table#kurosawa thead tr {
	background: #000;
	color: #fff;

We've used a dynamic background image to fill the table and are using <thead> as a parent in a descendant selector to change the header row; aside from that, the CSS is fairly straightforward. Next, we want to zebra-stripe the rows in the table body:

table#kurosawa tbody tr:nth-child(odd) { 
	background: rgba(0,0,0,0.3);

To highlight the rows on hover:

table#kurosawa tbody tr:hover {
	background: rgba(0,0,0,0.8);
	color: #fff;
	cursor: pointer;

Finally, we want to be able to highlight each column. Unfortunately, <col> supports very few CSS properties, and can't take most pseudo-selectors. Instead, we'll use :target from links in the table header section. To do so, we'll modify the markup slightly:

<table id="kurosawa">
	<col id="filmtitle">
	<col id="releasedate">
	<col id="runtime">
		<caption>The Masterworks of Akira Kurosawa</caption>
			<th><a href="#filmtitle">Title</a>
			<th><a href="#releasedate">Year of Release</a>
			<th><a href="#runtime">Run Time</a>

Now each table header cell has an anchor link to the <col> it is part of. Next, we customize the links:

table#kurosawa thead tr th a {
	text-decoration: none;
	color: #fff;
	background: #000;
	padding: .5em;
	display: block;
table#kurosawa thead tr th a:hover {
	background: #777;

And then the neat part: make each column highlight when it is targeted by the appropriate link.

table#kurosawa col:target {
	background: rgba(255,0,0,0.5);
	color: white;

<col> can be placed almost anywhere in a table: I've put the tags at the very top in order to minimize "bouncing" of the page when the local anchor link is followed. Because col elements are rendered on "top" of the existing content, using rgba colours creates a nice layered effect. It's also possible to "zebra stripe" cols using CSS; for example:

table#kurosawa col:nth-child(odd) {
	background: rgba(255,0,0,0.3);

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.