First of all, I’m with you: use tags semantically. But what if, semantically, unordered/ordered list groupings made the most sense … yet establishing relationships between separate lists via a visual layout (tables, in the case of my example) could enrich a user’s understanding of the data/content in question?
I guess the first issue would be to justify (on a semantic level, not a visual level) the grouping of data into HTML lists rather than HTML tables. The reasons why I’d use HTML lists would be to take advantage of their inherent hierarchical relationships and the extensibility they provide.
Both ordered and unordered list items belong to their parent lists, and content within a list item belongs to that list item, including entire other lists. And while this relationship isn’t as pure as the nodal relationship of something like XML, it’s only one step removed, and far easier to practically apply (and justify) than a nested table hierarchy.
If the use of HTML lists is semantically justified, then the next step would be to decide how best to present the data – taking into consideration the technical constraints and realities of web authoring. To support the formatting of lists as tabular rows or columns, I would cite the ability to juxtapose individual attributes of nested data, provided that corresponding individual attributes align when the nested data is presented visually.
Neither lists nor tables are the “right” markup for presenting information online as a table; they both have advantages and disadvantages. I suppose we’d have to look to our friends in library science for a perfect solution, but I don’t know much about that, so I’ll let someone else pick up the conversation at this point if they’re interested.
And conversation is really all I wanted out of my whole experiment in the first place. Well, that and more options for structuring and displaying data.
Thanks, Jop, for getting me thinking.
And by the way, Mr. Miller – identifying odd rows with scripting to free up class attributes is an awesome idea. Thanks for the great article!
You’re absolutely right about using lists instead of tables. I mean how should the result, the thing that everyone looks at, matter, instead of the code, the thing that only you look.
In case you can’t tell I’m being sarcastic. I don’t have anything against lists, but they’re getting annoying when they’re overused. Use Tables for tabular data; that way you have backwards compabibility.
I’ve found using this table style in our customer login, that customers find it easier to follow and read a table when it is printed like this. Giving a clear avantage on using it.
Copy & paste the code below to embed this comment.
Bruce Hodo
One other problem with IE is that it doesn’t handle tbody’s the way it should (i.e. allowing scroll bars just on the tbody {overflow:scroll} like REAL browsers do!). So, to enhance readability on long tables where the column headings scroll off of the page, I insert additional heading rows using tr>th’s often enough to insure there is at least 1 column header row on the screen at any time.
I modified eelco’s .zebra class code to the following:
Since I only had one table on the page (or I might want all of the tables to stripe), I applied it universally in that page. One could use eelco’s original .zebra class to apply it discreetly, if one wanted to. And because I used th’s on the inserted column header rows, it ignores those rows.
By the way, the ability to put a javascript expression in css to access the DOM is a pretty good idea, and might be a useful addition to css(3?). A decent idea from Microsoft? Who knew!
Copy & paste the code below to embed this comment.
Sean
This is exactly the trick I need to improve my tables on my site. However, I cant get this to work for my pages since they have two tables on each page. JavaScript is loaded, onload is in <body> tag, but nothing happens!
Any help? For those willing to help me troubleshoot my issues, please email me at s1smith@citicorp.com.
I’ve started a CSS3 Tests site if anyone’s interested. See http://www.geocities.com/seanmhall2003/css3/
I don’t think any browser supports the even/odd selectors.
Copy & paste the code below to embed this comment.
Dan Obenhaus
“
Has anyone managed to get this to work together with Stuart Langridge’s SortTables?
If anyone manages this please let me know.
“
Because of Safari’s (hence OmniWeb’s) broken rows & cells collections, Stuart Langridge’s SortTables won’t work in those browsers—from looking at his code—so construct your own arrays instead:
// make 2-D array to substitute for rows & cells collections
function addRowsArray(a_oTBody) {
var l_aRows = a_oTBody.getElementsByTagName(‘TR’);
for (var i = 0; i < l_aRows.length; i++) {
l_aRows.Cells = new Array;
for (var j = 0, k = 0; j < l_aRows.childNodes.length; j++) {
if (l_aRows.childNodes[j].nodeType == 1) {
l_aRows.Cells[k++] = l_aRows.childNodes[j];
}
}
}
a_oTBody.Rows = l_aRows;
return a_oTBody;
}
As for re-striping the table, immediately after sorting apply something like:
var i = 0;
do {
TBody.Rows.className = (i % 2 ? ‘oddClass’ : ‘evenClass’);
// or
TBody.Rows.style.background = (i % 2 ? ‘oddColor’ : ‘evenColor’));
} while (TBody.Rows[++i]);
(NOTE: Apple fixed the rows/cells bugs a few weeks ago in release 1.2; OmniWeb still manifests them.)
What about this:
<table ocolor=”#fff” ecolor=”#eee”>
With the script you could do stuff like:
var x = document.getElementsByTagName(“table”);
for (var i=0;i<x.length;i++) {
if (x.getAttribute(“ocolor”)) {
..stripe the table…
}
}
Easy, cool, and useful.
Copy & paste the code below to embed this comment.
pikkis
Wouldn’t it be useful to have CSS lists instead of tables when bringing content from another program, say a word document w/ tabs, then you could copy/paste only rows instead of each cell? Or?
Copy & paste the code below to embed this comment.
altran
Anyone know how to do this? I want zebra tables, but need a row to change to a certain other color when the mouse hovers over it. This needs to work in IE… :(
Definitely a worthwhile technique in my opinion, and works great in html files, but I am having some issues getting the script to execute correctly on a cfm app written in fuseQ.
The URL: http://www.gorebiz.co.nz/fbx_test/super12/index.cfm?fuseaction=home.results
Any ideas on what I am doing wrong? The Code looks fine to me.
Copy & paste the code below to embed this comment.
Ian
When I use the same id more than once my code doesn’t validate for xhtml. Is there a way to use this javascript by using class rather than id tags? (I’m a beginner)
Copy & paste the code below to embed this comment.
Dan Obenhaus
Ian, as the script stands you cannot. However, you may give each table its own id, then call each in succession:
|
onload=“stripe(‘id1’, ‘#fff’, ‘#eee’);stripe(‘id2’, ‘#fff’, ‘#eee’);stripe(‘id3’, ‘#fff’, ‘#eee’);”
|
Inelegant, but at least you don’t have to change the script. Good luck!
This helps a lot on people who have a hard time of seeing what info is “all” on the line if there is a blank space between, thanks for the great article.
You know, sometimes I’m surfing all night reading stuff like this in the hope to find something good, and sometimes I do. Like now.
About the Laptop/Handheld/Palmtop/whatever, it is possible to make a style sheet selector wich will have a high-contrast one in it… of course you could check for the OS and predefine the standard stylesheet, but hey, why not?
Copy & paste the code below to embed this comment.
AJ
I use Jop’s alternate script but I just want to apply it to tables with my a specific class an i can’t make out the javascript to do it.
As it is now it is:
var tables = document.getElementsByTagName(“table”);
I guess it should be something like:
var tables = document.getElementsByClassName(“stripedtable”);
but it doesn’t work. Anyone knows why?
There’s also a bug when I’m trying to have another class on a <tr> like the “selected” class in the original. It works well in IE but in Opera the background of some the row above gets weird. Someone wrote something about the best way to add multiple classes from the javascript.
As it goes now in Jop’s script it’s:
if (! hasClass(trs) && ! trs.style.backgroundColor) {
trs.className = even ? “even” : “”;
AFter reading this tbrough I believe it is easier to code the alternate bar class as odd then use CSS to set the colors. When changing a table with DW I just use the table command to modify the colors. If I was using a database to populate the table then I would have to use a script (of some kind) but not being a java coder (I use VBscript and .asp pages) I find this a pain, as I don’t want to learn another language (having used BASIC and its variants for 40 years.) I use programming tools as adjuncts to teaching medicine.
Copy & paste the code below to embed this comment.
Anthony
the tables look cool but when you print them they look like crap. i have designed a solution where but its not well designed as what i do is insert a layer (that has an image that is a color and the size of the layer) underneath every other row or marked row to give it a background color. so when you print the zebra tables it looks as cool on the screen, but i am thinking there is got to be a more classful way to do what i’ve done. anyone interested in seeing this?
any suggestions?
function colorize(itemLoc){
var fullText = document.getElementById(itemLoc);
var allLists = fullText.getElementsByTagName(“ul”);
var allTables = fullText.getElementsByTagName(“table”);
for (i=0; i<allLists.length; i++){
if (allLists.className==“stripedList”){
var colorElements = allLists.getElementsByTagName(“li”);
for (var j=0; j<colorElements.length; j+=2){
colorElements[j].className += “ dark”;
}
}
}
for (k=0; k<allTables.length; k++){
if (allTables[k].className==“stripedTable”){
var colorElements = allTables[k].getElementsByTagName(“tr”);
for (var l=0; l<colorElements.length; l+=2){
colorElements[l].className += “ dark”;
}
}
else if (allTables[k].className==“checkeredTable”){
var colorElements = allTables[k].getElementsByTagName(“td”);
for (var m=0; m<colorElements.length; m+=2){
colorElements[m].className += ” dark”;
m += 3;
if (m < colorElements.length){
colorElements[m].className += ” dark”;
}
m -= 1;
}
}
}
}
‘content’ is the id of the element (in most cases, probably a div) inside of which you want to look for items to be zebra-striped. So, for example, on the site I used this for, div#content contains various lists with the class of “stripeList,” various tables with the class of “stripeTable,” and other tables with the class of “checkeredTable” (the last of which is a table with two columns, many rows, to which a style is applied (going left-to-right, row by row) to its first cell, then it’s fourth cell and fifth cell, then its eighth and nineth, and so on and so forth).
This is evil:
<body >
Because it does not seperate behaviour and structure. Instead in the JS file put
window.onload = function;
Seperating Behaviour and Strucure is very important.
Copy & paste the code below to embed this comment.
Ryan Nichols
Hey Tim,
I disagree. I went back and reviewed your lists as tables. The examples you show aren’t semantically correct, and don’t have the correct relationships that a table would.
First look at it with style sheets turned off. The first ‘list item’ are the column headers. Then the subsequent list items are rows of ‘items’ and thier data, yet thier shown hiearchically the same as the headers. The first ‘list item’ of headers is a completely different type of data than the remaining ‘list items’ and this is reflected nowhere in the code.
Only a table can show the correct relationship by designating header data in a THEAD, and the body data in a TBODY. Tables also have the capability of linking individual cells with thier appropriate header, something the list example cannot do. The columns can be given a ‘title’ attirbute to add further information about the column, and because of the relationships, that title data is linked to each cell underneath it further describing the content.
Third and final point is cells don’t always have only one header. Cells can often have larger parent headers spanning two columns, and subheads spanning one column each underneath that.
View this link on the WC3 for an example. It’s a paragraph or two down the page.
97 Reader Comments
Back to the ArticleTim Brown
Hey Jop,
Thanks for the kind words!
First of all, I’m with you: use tags semantically. But what if, semantically, unordered/ordered list groupings made the most sense … yet establishing relationships between separate lists via a visual layout (tables, in the case of my example) could enrich a user’s understanding of the data/content in question?
I guess the first issue would be to justify (on a semantic level, not a visual level) the grouping of data into HTML lists rather than HTML tables. The reasons why I’d use HTML lists would be to take advantage of their inherent hierarchical relationships and the extensibility they provide.
Both ordered and unordered list items belong to their parent lists, and content within a list item belongs to that list item, including entire other lists. And while this relationship isn’t as pure as the nodal relationship of something like XML, it’s only one step removed, and far easier to practically apply (and justify) than a nested table hierarchy.
If the use of HTML lists is semantically justified, then the next step would be to decide how best to present the data – taking into consideration the technical constraints and realities of web authoring. To support the formatting of lists as tabular rows or columns, I would cite the ability to juxtapose individual attributes of nested data, provided that corresponding individual attributes align when the nested data is presented visually.
Neither lists nor tables are the “right” markup for presenting information online as a table; they both have advantages and disadvantages. I suppose we’d have to look to our friends in library science for a perfect solution, but I don’t know much about that, so I’ll let someone else pick up the conversation at this point if they’re interested.
And conversation is really all I wanted out of my whole experiment in the first place. Well, that and more options for structuring and displaying data.
Thanks, Jop, for getting me thinking.
And by the way, Mr. Miller – identifying odd rows with scripting to free up class attributes is an awesome idea. Thanks for the great article!
Dante-Cubed
You’re absolutely right about using lists instead of tables. I mean how should the result, the thing that everyone looks at, matter, instead of the code, the thing that only you look.
In case you can’t tell I’m being sarcastic. I don’t have anything against lists, but they’re getting annoying when they’re overused. Use Tables for tabular data; that way you have backwards compabibility.
David Jones - Elegant Design
I’ve found using this table style in our customer login, that customers find it easier to follow and read a table when it is printed like this. Giving a clear avantage on using it.
Bruce Hodo
One other problem with IE is that it doesn’t handle tbody’s the way it should (i.e. allowing scroll bars just on the tbody {overflow:scroll} like REAL browsers do!). So, to enhance readability on long tables where the column headings scroll off of the page, I insert additional heading rows using tr>th’s often enough to insure there is at least 1 column header row on the screen at any time.
I modified eelco’s .zebra class code to the following:
tr td {
background: [removed]this.parentElement.rowIndex%2 ==
1?’#ffdd99’:’#ffcc66’);
}
Since I only had one table on the page (or I might want all of the tables to stripe), I applied it universally in that page. One could use eelco’s original .zebra class to apply it discreetly, if one wanted to. And because I used th’s on the inserted column header rows, it ignores those rows.
By the way, the ability to put a javascript expression in css to access the DOM is a pretty good idea, and might be a useful addition to css(3?). A decent idea from Microsoft? Who knew!
Sean
This is exactly the trick I need to improve my tables on my site. However, I cant get this to work for my pages since they have two tables on each page. JavaScript is loaded, onload is in <body> tag, but nothing happens!
Any help? For those willing to help me troubleshoot my issues, please email me at s1smith@citicorp.com.
Dante Evans
I’ve started a CSS3 Tests site if anyone’s interested. See http://www.geocities.com/seanmhall2003/css3/
I don’t think any browser supports the even/odd selectors.
Dan Obenhaus
“
Has anyone managed to get this to work together with Stuart Langridge’s SortTables?
If anyone manages this please let me know.
“
Because of Safari’s (hence OmniWeb’s) broken rows & cells collections, Stuart Langridge’s SortTables won’t work in those browsers—from looking at his code—so construct your own arrays instead:
// make 2-D array to substitute for rows & cells collections
function addRowsArray(a_oTBody) {
var l_aRows = a_oTBody.getElementsByTagName(‘TR’);
for (var i = 0; i < l_aRows.length; i++) {
l_aRows.Cells = new Array;
for (var j = 0, k = 0; j < l_aRows.childNodes.length; j++) {
if (l_aRows.childNodes[j].nodeType == 1) {
l_aRows.Cells[k++] = l_aRows.childNodes[j];
}
}
}
a_oTBody.Rows = l_aRows;
return a_oTBody;
}
As for re-striping the table, immediately after sorting apply something like:
var i = 0;
do {
TBody.Rows.className = (i % 2 ? ‘oddClass’ : ‘evenClass’);
// or
TBody.Rows.style.background = (i % 2 ? ‘oddColor’ : ‘evenColor’));
} while (TBody.Rows[++i]);
(NOTE: Apple fixed the rows/cells bugs a few weeks ago in release 1.2; OmniWeb still manifests them.)
Dan Obenhaus
“
There is a something similar at BrainJar: http://brainjar.com/dhtml/tablesort/.
“
Brainjar’s (otherwise brilliant) code has the same weakness. Do not assume native collections work simply because they exist.
If you make your own arrays by coursing through the nodes of the tables, you know what to expect.
Dante-Cubed
What about this:
<table ocolor=”#fff” ecolor=”#eee”>
With the script you could do stuff like:
var x = document.getElementsByTagName(“table”);
for (var i=0;i<x.length;i++) {
if (x.getAttribute(“ocolor”)) {
..stripe the table…
}
}
Easy, cool, and useful.
pikkis
Wouldn’t it be useful to have CSS lists instead of tables when bringing content from another program, say a word document w/ tabs, then you could copy/paste only rows instead of each cell? Or?
altran
Anyone know how to do this? I want zebra tables, but need a row to change to a certain other color when the mouse hovers over it. This needs to work in IE… :(
Andrey Semchuk
But scheme from Ned Baldessin isn’t work for me :(
Mark H
Definitely a worthwhile technique in my opinion, and works great in html files, but I am having some issues getting the script to execute correctly on a cfm app written in fuseQ.
The URL: http://www.gorebiz.co.nz/fbx_test/super12/index.cfm?fuseaction=home.results
Any ideas on what I am doing wrong? The Code looks fine to me.
adieu
Mark
DUNSEL
And take the call out of the body tag.
[removed]
onload = function() { tableChange () };
function tableChange()
{
var rows = window.document.getElementsByTagName(‘tr’);
for(var i = 0; i < rows.length; i++)
{
(i%2==0)? rows.item(i).style.backgroundColor = “lightblue” : rows.item(i).style.backgroundColor = “E0EFEE”
} }
[removed]
FuzzyWuzzy
I’ve made a function to create rows
but the zebra patern is not quite working.
Can someone help me out here?
function crtrow($tabel, $text) {
if (!empty($tabel)) {
if ($class == “even”) $class=“odd”; else $class=“even”;
echo(”<tr class=$class>
<td>$text</td>
<td>$tabel</td>
</tr>”);
}
}
Ian
When I use the same id more than once my code doesn’t validate for xhtml. Is there a way to use this javascript by using class rather than id tags? (I’m a beginner)
Dan Obenhaus
Ian, as the script stands you cannot. However, you may give each table its own id, then call each in succession:
|
onload=“stripe(‘id1’, ‘#fff’, ‘#eee’);stripe(‘id2’, ‘#fff’, ‘#eee’);stripe(‘id3’, ‘#fff’, ‘#eee’);”
|
Inelegant, but at least you don’t have to change the script. Good luck!
Matt Gilley
This helps a lot on people who have a hard time of seeing what info is “all” on the line if there is a blank space between, thanks for the great article.
Mathijs
You know, sometimes I’m surfing all night reading stuff like this in the hope to find something good, and sometimes I do. Like now.
About the Laptop/Handheld/Palmtop/whatever, it is possible to make a style sheet selector wich will have a high-contrast one in it… of course you could check for the OS and predefine the standard stylesheet, but hey, why not?
Mathijsken
AJ
I use Jop’s alternate script but I just want to apply it to tables with my a specific class an i can’t make out the javascript to do it.
As it is now it is:
var tables = document.getElementsByTagName(“table”);
I guess it should be something like:
var tables = document.getElementsByClassName(“stripedtable”);
but it doesn’t work. Anyone knows why?
There’s also a bug when I’m trying to have another class on a <tr> like the “selected” class in the original. It works well in IE but in Opera the background of some the row above gets weird. Someone wrote something about the best way to add multiple classes from the javascript.
As it goes now in Jop’s script it’s:
if (! hasClass(trs) && ! trs.style.backgroundColor) {
trs.className = even ? “even” : “”;
Christopher Buttery
AFter reading this tbrough I believe it is easier to code the alternate bar class as odd then use CSS to set the colors. When changing a table with DW I just use the table command to modify the colors. If I was using a database to populate the table then I would have to use a script (of some kind) but not being a java coder (I use VBscript and .asp pages) I find this a pain, as I don’t want to learn another language (having used BASIC and its variants for 40 years.) I use programming tools as adjuncts to teaching medicine.
Anthony
the tables look cool but when you print them they look like crap. i have designed a solution where but its not well designed as what i do is insert a layer (that has an image that is a color and the size of the layer) underneath every other row or marked row to give it a background color. so when you print the zebra tables it looks as cool on the screen, but i am thinking there is got to be a more classful way to do what i’ve done. anyone interested in seeing this?
any suggestions?
Marc Palau
Hi.
I see the itunes screenshot that u put here and i can’t remedy my dhtml obsession of clone all i see :P…
here u have a adaptation of u’r idea to just do that itunes do (i don’t know if the mouseover that i put exists on itunes but it’s there).
http://www.palaueb.com/javascript/dhtml/itunes.htm
ah! u only need to write the name of song and the artist, the script itself do the count and attach the checkbox.
Blair Miller
Here’s what I came up with:
// apply alternating classes to lists or tables
function colorize(itemLoc){
var fullText = document.getElementById(itemLoc);
var allLists = fullText.getElementsByTagName(“ul”);
var allTables = fullText.getElementsByTagName(“table”);
for (i=0; i<allLists.length; i++){
if (allLists.className==“stripedList”){
var colorElements = allLists.getElementsByTagName(“li”);
for (var j=0; j<colorElements.length; j+=2){
colorElements[j].className += “ dark”;
}
}
}
for (k=0; k<allTables.length; k++){
if (allTables[k].className==“stripedTable”){
var colorElements = allTables[k].getElementsByTagName(“tr”);
for (var l=0; l<colorElements.length; l+=2){
colorElements[l].className += “ dark”;
}
}
else if (allTables[k].className==“checkeredTable”){
var colorElements = allTables[k].getElementsByTagName(“td”);
for (var m=0; m<colorElements.length; m+=2){
colorElements[m].className += ” dark”;
m += 3;
if (m < colorElements.length){
colorElements[m].className += ” dark”;
}
m -= 1;
}
}
}
}
Call it from the body tag using:
<body >Blair Miller
‘content’ is the id of the element (in most cases, probably a div) inside of which you want to look for items to be zebra-striped. So, for example, on the site I used this for, div#content contains various lists with the class of “stripeList,” various tables with the class of “stripeTable,” and other tables with the class of “checkeredTable” (the last of which is a table with two columns, many rows, to which a style is applied (going left-to-right, row by row) to its first cell, then it’s fourth cell and fifth cell, then its eighth and nineth, and so on and so forth).
Dante
This is evil:
<body >
Because it does not seperate behaviour and structure. Instead in the JS file put
window.onload = function;
Seperating Behaviour and Strucure is very important.
Ryan Nichols
Hey Tim,
I disagree. I went back and reviewed your lists as tables. The examples you show aren’t semantically correct, and don’t have the correct relationships that a table would.
First look at it with style sheets turned off. The first ‘list item’ are the column headers. Then the subsequent list items are rows of ‘items’ and thier data, yet thier shown hiearchically the same as the headers. The first ‘list item’ of headers is a completely different type of data than the remaining ‘list items’ and this is reflected nowhere in the code.
Only a table can show the correct relationship by designating header data in a THEAD, and the body data in a TBODY. Tables also have the capability of linking individual cells with thier appropriate header, something the list example cannot do. The columns can be given a ‘title’ attirbute to add further information about the column, and because of the relationships, that title data is linked to each cell underneath it further describing the content.
Third and final point is cells don’t always have only one header. Cells can often have larger parent headers spanning two columns, and subheads spanning one column each underneath that.
View this link on the WC3 for an example. It’s a paragraph or two down the page.
http://www.w3.org/TR/html401/struct/tables.html#adef-headers