Zebra Tables

by David F. Miller

97 Reader Comments

Back to the Article
  1. It would be quite easy to change that JS to support tables with 3 row colours (1,2,3,1,2,3,etc.)—heck, any number of colours!—instead of just two.

    Copy & paste the code below to embed this comment.
  2. PHP can handle this really well, and would be easy to modify to include more row colors, like Colin suggested. Here’s how I do it:

    <?php
    if (!isset($bgflag)) $bgflag = 0;
    if ($bgflag == 1) {
    echo ‘<tr valign=“top”>’;
    $bgflag = 2;
    } else {
    echo ‘<tr valign=“top” bgcolor=“E3ECED”>’;
    $bgflag = 1;
    }
    ?>

    Copy & paste the code below to embed this comment.
  3. re: “And because we aren’t applying classes to any of the table rows to achieve the effect, we can use classes for more specific uses”
    Why not apply classes? The rows can quite hapily have more than one class (it just means that instead of saying element.className=‘foo’, you have to say element.className+=‘foo’, and check whether element.className already contains ‘foo’), and then you can control the styles from in your stylesheet, rather than by editing the Javascript. Moreover, you could control the styles separately for separate tables by just putting “table.specificId tr.odd { background-color: whatever; }” or similar. I think it’d be nicer if it automatically “stripe-ized” all tables with class “stripe”, too, rather than having to code a specific JS call in body.onload.
    All those minor points aside, it’s a neat script; thanks!

    Copy & paste the code below to embed this comment.
  4. This article lists as an advantage of the technique that one “can now use classes for more specific uses in the table” when not using classes for striping. Keep in mind that you can have multiple classes per element, like <tr class=“even selected”> – in this case, CSS rules selecting “.even” and “.selected” will both be in effect.

    Copy & paste the code below to embed this comment.
  5. Great article. Thank you!

    Sil makes a good point. Putting classes in the table is probably a good thing, as it will allow non-ECMA Script/DOM-aware browsers a chance to see the pretty colours.

    Very handy indeed!

    Copy & paste the code below to embed this comment.
  6. This looks like a great technique to apply—I know I’ve been driven to fits before by needing to re-stripe an entire table because of shifting data (thank god for grep search/replace).

    And you used Tegan & Sara in your example table! Sweet.

    Copy & paste the code below to embed this comment.
  7. Several CSS3 selectors do this exactly : tr:nth-child(even) and tr:nth-child(odd).

    See http://www.w3.org/TR/css3-selectors/#nth-child-pseudo for more details.

    Of course, no browsers are even close to support the spec (it’s a CR, written in 1999 !). Yawn.

    Copy & paste the code below to embed this comment.
  8. I’ve used this code quite happily:

    http://www.kryogenix.org/code/browser/sorttable/

    It allows you to sort tables with Javascript (e.g., click on the “Last Name” header to sort by last name, click again to sort reverse, etc).  One little problem is that when I’ve used it with server-generated odd/even row classes, the odds and evens aren’t correct after the sort, so it looks kind of funny.  It’s not a big enough of a deal for me to go to a server-side solution (people will appreciate the speed of client-side sorting more than the aesthetics of the row colors) but it would be nice to combine the two.  (Even better with some of the small modifications I made to it at http://ianbicking.org/software/sorttable-ib.js )

    Copy & paste the code below to embed this comment.
  9. I ran into this issue while maintaining a table-based family e-mail address list. Rather than using an “even” flag, I use the modulo operator “%” to determine if the row count index is divisble by 2. I only use one table body for the list, so this works fine for me.

    Copy & paste the code below to embed this comment.
  10. Just something I’ve noticed a lot with the very pale colors used in the examples and in a number of other striped tables I’ve seen recently: On LCD monitors, especially on notebooks, there’s little contrast between colors with similar luminance in the white and blue hues. In the examples shown in this article I could not see the difference between rows without assuming a different viewing angle. This proved true on both the laptops on my desk at the moment, and both my Mac and PC laptops at home.

    Copy & paste the code below to embed this comment.
  11. I see no light blue shaded lines in IE5.5. All white background except for the three selected lines.  Is this a problem with IE5.5 or is it just me.

    Copy & paste the code below to embed this comment.
  12. This CSS does the trick. But not in IE 6 that a bummer.

        .even + .odd
        {
          background-color: #EEE;
        }
       
        .odd + .even
        {
          background-color: #FFF;
        }

    Copy & paste the code below to embed this comment.
  13. Does not make any sense. Sorry. Please ignore.

    Copy & paste the code below to embed this comment.
  14. I just had to comment on The Weakerthans and the great “Plea from a Cat Named Virtue” being on that list—that band is awesome.

    oh, and cool technique, too!

    Copy & paste the code below to embed this comment.
  15. Every song by a Canadian artist… woot woot.

    Copy & paste the code below to embed this comment.
  16. These alternating stripes have their origin the the lineprinter paper from the 1970s.  We called it “greenbar”.

    Copy & paste the code below to embed this comment.
  17. Although I’ve used a similar method in the past, I would suggest one modification: don’t set the background color in the script.  Just use the script to apply the even/odd classes so you can keep the styling in the stylesheet.  That makes it cleaner to work with, and it’s much easier to add extra styling (borders, fonts, etc.).

    Then, instead of checking for the existence of a previous class, you just add a class to the element:

    node.className += ” even”;

    (Notice the space before the class name so you don’t end up with “fooeven” when the original class name was “foo”.)

    I think handing the styling control back to CSS and just automating the assignment of classes makes this solution better suited for web designers who don’t want to muddle with the JavaScript.

    Copy & paste the code below to embed this comment.
  18. Putting that className advice condenses stripe to a five line function.

    I’ve posted redo of the example page at
    http://davious.org/onepagers/anewstripe.html

    I also agree the row classing belongs in the hands on a dynamic markup templating system.

    Copy & paste the code below to embed this comment.
  19. // On a site I made, I was displaying links to, and info about, a handful of
    // MP3s, and opted to use an iTunes style layout. I found it nice to add this
    // bit. Each cell is a link to its respective file, and when hovered, it
    // displays the iTunes selected color. Unfortunately, only Gecko renders it
    // properly. This is how it was acheived:

    td a {
    color:  #000000 !important;
    background:  transparent;
    display:  block;
    text-decoration:  none;
    margin:  0px 0px 0px -1px;
    border-left:  1px solid #D9D9D9;
    border-right:  1px solid #D9D9D9;
    }
    tr.odd td a {
    color:  inherit;
    background:  #ECF2FE;
    }
    tr.even td a {
    color:  inherit;
    background:  #FFFFFD;
    }
    tr:hover td a {
    color:  #FFFFFF !important;
    background:  #3D80DF !important;
    border-color:  #346DBE;
    }

    Copy & paste the code below to embed this comment.
  20. This technique is good for short to moderately long lists.  Designers should beware that slower machines (Pentiums are still out there – or old Macs too) will hit this code and slowly churn through the table rows.

    Thanks for the useful code!

    Copy & paste the code below to embed this comment.
  21. For IE only intranets:

    .zebra tr {
      background: [removed]this.rowIndex%2 == 1?’#F0F0F0’:’#FFF’);
    }

    /eelco

    Copy & paste the code below to embed this comment.
  22. Why don’t you apply the classes?

    window.onload = function() {
      var trs = document.getElementByTagName(‘tr’);
      for (var i = 0; i < trs.length; i++)
      if (i%2) { trs[ i ].addAttribute(‘class’, ‘odd’) }
    }

    That won’t work in IE, but there are alternate methods to addAttribute.

    Copy & paste the code below to embed this comment.
  23. This article is something that I have been looking out for a long time. Unfortunately I switched from tables to lists using css on my new page (not published jet).

    Probably it is not difficult to change the script to lists, but I have no idea how to do that.

    Would be great if someone could change that script.

    Besides that I would be interested if the same thing could be done server based ? Important because I know too many people who switch of JS completely.

    Matthias Pospiech

    Copy & paste the code below to embed this comment.
  24. Isn’t it a Plea From a Cat Named Virtue?

    Copy & paste the code below to embed this comment.
  25. Use the className property for setting classes. Don’t use addAttribute.

    Copy & paste the code below to embed this comment.
  26. I’ve been looking for different ways to display tabular data and I’ve often used the code from http://www.tbrown.org/ideas/tabularlist/ to eliminate the table completely. This will work well in conjunction with that.

    Copy & paste the code below to embed this comment.
  27. First of all, nice work.
    I was thinking about writing some script like this a while ago but never came to it.
    After reviewing your code I figured that it could be a bit more efficient though, as like other mentioned, with the use of classes. Also I think that the script iterates one level too many, why not just give the tr a classname and therin specifying the background color for the individual td’s.

    I’ve rewritten the script a bit, it iterates through all the tables in the page (I don’t use the id part, since I want all tables ‘zebra-d’).

    The script can be found at http://validweb.nl/zebra.txt

    The CSS I use looks like this:
    table tr.even td{
    background-color: color;
    }

    Copy & paste the code below to embed this comment.
  28. Has anyone managed to get this to work together with Stuart Langridge’s SortTables? By together I mean, when you click the header to resort the table, have the zebra function rescan the table so that the effect remains.

    If anyone manages this please let me know.

    I tried calling stripe() from within various points of the sortable code, but I can’t get it to call it.

    Copy & paste the code below to embed this comment.
  29. It’s kind of neat to stripe a table, then have a third color show up onMouseOver.

    It’s pretty straight forward from the concepts covered here, but PHPMyAdmin on Sourceforge has a good example in it’s interface.  In fact, PHPMyAdmin has functionality where you can click a row, or many rows, and have it stay that alternate 3rd color, which is nice for picking out records in large tables/databases.

    Copy & paste the code below to embed this comment.
  30. Why did you use multiple <TBODY>‘s in the example. A table could just have one BODY or am I wrong?

    Copy & paste the code below to embed this comment.
  31. There is a something similar at BrainJar: http://brainjar.com/dhtml/tablesort/. It is old but works well across all browsers (DOM). With a couple of modifications it can also validate against (X)HTML. Disadvantage are that the code is long and not-so easy to modify, and the sorting is a bit slow for very long tables. I also found this: http://webfx.eae.net/dhtml/tablesort/tablesort.html at WebFX. It is faster but the external script required is also large. A Langridge/Zebra approach would be the optimal solution. Is anybody has managed to combine both scripts I would appreciate if you could post the code.

    Copy & paste the code below to embed this comment.
  32. For the people that wanted striping with lists, here you go:

    function stripeList(theList, oddClass, evenClass)
    {
      //stripes a list’s items
      //parameters: a reference to the list you want striped (theList), the class name for odd numbered items, and the class name for even numbered items
      var listItems = theList.getElementsByTagName(“li”), i=0, currentItem;
      while (currentItem = listItems[i++])
      {
      if (i % 2 == 0)
      {
        currentItem.className = evenClass;
      }
      else
      {
        currentItem.className = oddClass;
      }
      }
    }

    To run it, just use something like so:

    window.onload = function ()
    {
      stripeList(document.getElementById(“myList”), “oddRow”, “evenRow”);
    }

    Copy & paste the code below to embed this comment.
  33. Using a server side script ( I like using php the best) eliminates any issues with the browser. Not to mention if the user has javascript shut off.

    Copy & paste the code below to embed this comment.
  34. Ain’t no party like a Bran Van Party!

    Glad to see that in there!

    Go Discosis!

    Copy & paste the code below to embed this comment.
  35. <script type=“text/javascript”>
    //Powered by DCScript
    function zebra() {
    var node = document.getElementById(“zebra”);
    var tds = node.firstChild.firstChild.childNodes;
    for (var i=0;i<tds.length;i+=2) {
    var inc = eval(i+1);
    tds[ i ].style.backgroundColor=“blue”;
    tds[ inc ].style.backgroundColor=“green”;
    }
    } window.
    </script>

    Change the ID and the colors (or the onload bit). Correct me if this script is wrong. This was my initial thought has to how to create Zebra Tables. The firstChild.firstChild bit is for the TBODY tag (which is automatically generated by IE6).

    Copy & paste the code below to embed this comment.
  36. There’s another reason to set the class attribute.  The ‘style’ property (although supported by Mozilla and IE) is NOT part of the DOM or EMCAScript.

    Copy & paste the code below to embed this comment.
  37. According to W3C a table should have only one THEAD and TFOOT element, but may have many TBODYs.

    Copy & paste the code below to embed this comment.
  38. In order to properly work with multiple classNames from the DOM, you need better mechanisms for adding/removing classes than

    elem.classname += ’ class’;

    As others here have suggested.  Instead, I proffer this approach.

    ——————————————————-
    function removeClassName( elem, className )
    {
    elem.className = elem.className.replace( className, “” ).trim();
    }

    function addCSSClass( elem, className )
    {
    removeClassName( elem, className );
    elem.className = ( elem.className + ” ” + className ).trim();
    }

    String.prototype.trim = function()
    {
    return this.replace( /^\s+|\s+$/, “” );
    }
    ——————————————————-

    The functions can easily be attached to objects for namespace frugality.

    Copy & paste the code below to embed this comment.
  39. For all yall working in a Java / J2EE environment, and I know you are out there, check out the DisplayTag library at:

    http://www.displaytag.org/

    It’s a custom tag library for developing JSPs.  It makes data driven XHTML tabular output easy. 

    Copy & paste the code below to embed this comment.
  40. Great article! I’ve been looking for a way to automate this on static pages. While it’s true this won’t work with javascript turned off, if you’re not using a server side technology then there’s little else you can do.

    If, however, you’re using a server side technology to dynamically build your tables, this sort of thing is a walk in the park. Here’s one of many examples, this time using ColdFusion:

    In your table code:

    <tr class=”#IIf(CurrentRow Mod 2, DE(‘firstrow’), DE(‘secondrow’))#”>

    Now, just put two classes (.firstrow and .secondrow) in your CSS file and color/style them however you want.

    Copy & paste the code below to embed this comment.
  41. The above should be:

    <tr class=”#IIf(CurrentRow Mod 2, DE(‘firstrow’), DE(‘secondrow’))#”>

    I’ve gotten in the habit of typing &lt; instead of < because several of the boards I visit require it…hard to keep them all straight!

    Copy & paste the code below to embed this comment.
  42. I like this idea because with it you can really separate the content from the presentation.  If you’re doing the zebra-stripes on the server side and just adding <tr class=“foo”> for every other row then you’re mixing the content in.

    So in this case you’re using javascript as a way to better apply style to your (x)html.  As the author said, it’s another tool in the toolbelt.

    Copy & paste the code below to embed this comment.
  43. That might work, but not in IE5. The \s part messes it up. No idea why. IE6 has no problem though.

    Copy & paste the code below to embed this comment.
  44. I use a script that applies a class to alternating tbody elements when I want to group multiple rows together visually as well as structurally.

    Copy & paste the code below to embed this comment.
  45. Very nice article, particularly the adjustment part way through this thread to make it 5 lines of javascript. I do this [colored row] constantly for the admin sections of client sites… usually server side Cold Fusion or ASP. This javascript is a nice addition to the “toolbelt” as you say. At least with your clients you are [or should be] somewhat aware of the browser environment you are coding for. Thanks for the article! Also nice contributions by the readership… the Tim Brown list submission [that looks like a table] is a great example.

    Take care,
    Jim S.

    Copy & paste the code below to embed this comment.
  46. Just made a script which creates the zebra fx for any object in your HTML. Define the ID of the object and the tag which it should ‘zebra’.

    This example shows it for: table, selectbox and list.

    http://www.flashpro.nl/css/index.html

    One problem when adding one more list item in the nested structure it will hang. Anyone an idea on what is the cause of this?

    Copy & paste the code below to embed this comment.
  47. The method I use with PHP only takes one line to decide…

    $class = ($class == ‘odd’) ? ‘even’ : ‘odd’;

    ?>
    <tr class=”<?php echo $class”>…

    Copy & paste the code below to embed this comment.
  48. A few months ago I made a js to add classes to rows and/or columns.

    http://mrclay.org/tests/table_decoration/

    Currently it just adds classNames to all the odd TRs and column cells (TH or TD) in every table in the document the script is included in, but a more robust version is in the works.  Or go ahead and modify it.

    Copy & paste the code below to embed this comment.
  49. Pulling together several of the posts in this discussion, I have managed to come up with a pretty good way of having sortable striped tables that maintain their stripes even after a sort.

    Getting all of the code together in one coherent place isn’t my idea of fun, but here’s the general steps I followed to make everything play nice together:

    1. Get the sorting library mentioned earlier at: http://ianbicking.org/software/sorttable-ib.js.

    2. Get the new stripe function mentioned earlier at: http://davious.org/onepagers/anewstripe.html.

    3. Get the CSS class name functions mentioned in this comment: http://alistapart.com/discuss/zebratables/5/#c7078.

    4. Put all of these files in one Javascript file, or split them up. It really doesn’t matter, as long as they’re all included on the page.

    5. In the sorting functions, make two changes:

    a) In the sortables_init() function, after the table has been made sortable, call the stripe() function, being sure to pass it the table’s ID.

    b) In the ts_resortTable() function, call stripe() after all of the changes to the table are complete.

    6. In the stripe() function, there are two changes:

    a) In the ‘for’ loop, change the increment operation so it increments by one, not two.

    b) Instead of appending class names, use the CSS functions (from step 3) to remove the ‘even’ class from the row and then, if the row is an even one (i.e. i % 2 == 0), add the ‘even’ class to the row.

    7. In the CSS functions, I removed the first line from the addCSSClass() function, although it’s not necessary.

    Good luck!

    Copy & paste the code below to embed this comment.
  50. Nice work, well done!
    I tested it with the following browsers (all PC):

    - IE 5.5
    – IE 6.0
    – Netscape 7.0
    – Mozilla 1.5

    With Opera 7.0 I get the sorting right, but unfortunately the stripping doesn’t seem to work. Any work arounds anyone?

    Copy & paste the code below to embed this comment.
  51. Here we go
    <script type=“text/javascript”>
    //Powered by DCScript
    function zebra(tID,ecolor,ocolor) {
    var node = document.getElementById(tID);
    var tds = node.firstChild.firstChild.childNodes;
    for (var i=0;i<tds.length;i++) {
    var it=tds[ i ];
    var index=eval( i );
    if (index % 2 == 0)
    it.style.color=ecolor;
    else it.style.color=ocolor;
    }
    }
    </script>
    The first parameter is the table ID, then the color for evens, and then the colors for odd. Call it like
    <body onLoad=“zebra(‘data’,‘blue’,‘red’)”>

    Copy & paste the code below to embed this comment.
  52. It seems I’m rather late, ‘cause I saw Jop had already modified the script in almost the same matter. Anyways, here’s my version:

    http://www.codewarrior.nl/~bladibla/zebra/

    Copy & paste the code below to embed this comment.
  53. I’ve been struggling with this for a long time: why can’t I use CSS to make information display in the same tabular way that tables do?  It frustrates the heck out of me that W3C still hasn’t come up with a solution to this.  I can make it look nice w/ 2 columns or 3, but any more than that and I’m hosed.  As Z says: “Tables are dead . . . Long Live Tables”

    (ps – anyone who knows how to get past this is welcome to email me! mike@smallBLOC.com)

    but a great article all the same (i just tend to rant a little)

    Copy & paste the code below to embed this comment.
  54. If you are a designer and can’t write a simple function like this, you are going to be out of a job soon…let’s take a php example:

    <?php
      function getClass($Num)
      {
      if (($Num % 2) == 0)
      {
        return “Reg”;
      } 
      else
      {
        return “Alt”;
      } 
      }
    ?>

    Then on your table:

    <table>
    <tr class=“HeadRow”>
      <td>Blah</td>
      <td>Foo</td>
      <td>Bar</td>
    </tr>
    <?php
      foreach($DBStuff as $Stuff)
      {
        $RowClass = getClass($i);
        print(”<tr class=\”” . $RowClass . “\”>\n”);
        print(”<td>” . $Stuff->Blah . “</td>\n”);
        print(”<td>” . $Stuff->Foo . “</td>\n”);
        print(”<td>” . $Stuff->Bar . “</td>\n”);
        print(”</tr>\n”);
        $i++;
        }
    ?>
    </table>
       
    Then in your stylesheet, tell what tr.Reg and tr.Alt are supposed to look like:

    tr.Reg
    {
      background-color: #FFF;
    }
    tr.Alt
    {
      background-color: #E6E6E6;
    }

    If designers don’t start learning simple server side languages they won’t survive in the future market…

    Copy & paste the code below to embed this comment.
  55. In the case where you retrieve the table data from a database, a server-side language is obviously the better solution. But what about the case where you enter the data manually?

    Copy & paste the code below to embed this comment.
  56. Nice approach – I used to use PHP and a mod division to see which row was even or odd but the drawbacks to that approach are obvious. 

    Great tip!

    Copy & paste the code below to embed this comment.
  57. Am considering using this method for an html table builder plugin within a inhouse content management system, but one of the condieration is that it works in i.e 5.5.  The javascript listed does not support this method but by removing node from obj.getAttributeNode within the hasClass function works like a dream!  Also tested on i.e 6 and netscape 7+.

    Copy & paste the code below to embed this comment.
  58. server-side technologies are best

    Copy & paste the code below to embed this comment.
  59. If I wanted the even or odd row color background to be dark and I wanted the text in that row to be white, how would I accomplish this?

    Copy & paste the code below to embed this comment.
  60. eom

    Copy & paste the code below to embed this comment.
  61. Rob – if you want to change the text color in a table row/cell, then just specify that in your class, like so:

    .oddclass {
      background: #ffc;
      color: navy;
    }

    Copy & paste the code below to embed this comment.
  62. Just plug this code into the head, and call it in the body tag, and it will “zebra” any table on any HTML page:

    <script type=“text/javascript”>
    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”

    } }
    </script>

    Of course, this is just for alternating 2 colors. But no other code is needed. No class designations, no stylesheet, no nothing.

    Copy & paste the code below to embed this comment.
  63. Don’t use item( i ) in Javascript. Instead of rows.item( i ) use rows[ i ]. It’s a lot easier. Item is useless.

    But what if you have another table that you don’t want striped?

    Copy & paste the code below to embed this comment.
  64. Q. How do I apply this script to multiple tables in the same page? I tried using the same id for each, but am missing something.

    d.

    Copy & paste the code below to embed this comment.
  65. don -  I’ve just implemented the short version of this script into my new corporate site.  The site uses <gasp!> nested tables for layout <oh the shame!> – so obviously applying the zebra function to all tables would be right out. 

      I have pages with big lists of forms on them and was able to use this method to zebra them even on pages with several different list tables simply by removing the #playlist {border: 1px solid #666666;} and assigning the border to another class (which I called .stripedtable then putting a div around ALL the tables I want striped and assigning the id to the div. 

    I changed the css so that the various rules applied to only those tables of class stripedtable and not to the others.

    .stripedtable {border: 1px solid #666;}

    #coformlist table.stripedtable tbody tr.even td {background-color: #efefef;}

    it works a treat

    Copy & paste the code below to embed this comment.
  66. I’ve seen it happening around, people trying to make a list look/behave like a table. Can anyone please explain to me why this is being done? I mean, a table is a table after all. A list should (in my opinion) be a list (it doesn’t have to look like an ordinary list though).
    Is it that people think that tables are bad now? They not bad if used properly, this means used to display tabular data (I agree they’re bad when used for layout).

    For example, if I look at http://www.tbrown.org/ideas/tabularlist/ with CSS turned off, I get a few lists down in a row, this doesn’t give me the overview I get when looking at a table.
    I mean it’s nice just as an experiment, and I really think he has done a good job, but for displaying tabular data it looks no good to me (with css turned off).

    I thought that was the whole point of this new wave going on in webdesignerworld, use tags for what they are meant for. Sure you can style a div so that it would look like a regular blockquote, but we already have a tag for that, if you want it to look different, use CSS. Sure you can layout a website using tables, but that’s not what they’re meant for, besides they are other ways to accomplish that. I think most of the readers here at ALA will agree with me on that. But why do we want to make lists look like tables then?

    So can someone please explain what’s going on, am I missing something?
    Thanks alot,
    Jop

    Copy & paste the code below to embed this comment.
  67. When I used the javascript in my code, I tested it in my browser (Safari) and it was beautiful. However, when testing it in a PC environment and in IE for Mac, I noticed that in tables consisting of a lot of rows (100 or more) the alternating colors stop rendering. Is there a work around for this bug?

    Copy & paste the code below to embed this comment.
  68. I’ve managed this one pretty well in my second day of exploring CSS and the likes and got this one up and running pretty quick.

    However, after getting the hang of it, i tried to create a multi-table CSS row on the right site of my page and found out a pretty bizar problem which i can’t seem to solve:

    The first table is drawn ok as it should, but the second one only fills in the color for the class=“selected”.

    I’ve been trying to extend the css and different namings … no luck …

    I think it’s a problem of either import of the CSS (1 declaration of tr/td possible) or something is amis in the javascript.

    I also tried it with 2x the table code on the side and got the same result.

    Any help appreciated :)

    Copy & paste the code below to embed this comment.
  69. That’s the longest way I’ve ever seen of alternating rows in PHP :)

    $hl = false;
    while (…) {
      // code and markup leading to <tr …
      echo (($hl = !$hl)) ? “#fff” : “#eee”;
    }

    Copy & paste the code below to embed this comment.
  70. This is because the original script does accepts an ID, and as you might know, ID’s (opposed to classes) must be unique, which means you can only stripe one table per function call.
    So either you run the function with each seperate ID, or you modify the script to accept classes and iterate through all the items with that class.

    I’ve written a moduralized version of the script, which iterates through all the tables in a page (those without classes that is). 
    http://validweb.nl/zebra.txt

    but be sure to look around in the comments too, since other people have written excellent modifications as well which might suit you better!

    Copy & paste the code below to embed this comment.
  71. 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!

    Copy & paste the code below to embed this comment.
  72. 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.

    Copy & paste the code below to embed this comment.
  73. 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.
  74. 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!

    Copy & paste the code below to embed this comment.
  75. 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.

    Copy & paste the code below to embed this comment.
  76. 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.
  77. “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[ i ].Cells = new Array;
      for (var j = 0, k = 0; j < l_aRows[ i ].childNodes.length; j++) {
        if (l_aRows[ i ].childNodes[ j ].nodeType == 1) {
          l_aRows[ i ].Cells[k++] = l_aRows[ i ].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[ i ].className = (i % 2 ? ‘oddClass’ : ‘evenClass’);
    // or
      TBody.Rows[ i ].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.)

    Copy & paste the code below to embed this comment.

  78. 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.

    Copy & paste the code below to embed this comment.
  79. 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[ i ].getAttribute(“ocolor”)) {
    ..stripe the table…
    }
    }

    Easy, cool, and useful.

    Copy & paste the code below to embed this comment.
  80. 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.
  81. 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… :(

    Copy & paste the code below to embed this comment.
  82. But scheme from Ned Baldessin isn’t work for me :(

    Copy & paste the code below to embed this comment.
  83. 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

    Copy & paste the code below to embed this comment.
  84. And take the call out of the body tag.

    <script type=“text/javascript”>
    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”

    } }
    </script>

    Copy & paste the code below to embed this comment.
  85. 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>”);
        }
      }

    Copy & paste the code below to embed this comment.
  86. 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.
  87. 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!

    Copy & paste the code below to embed this comment.
  88. 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.

    Copy & paste the code below to embed this comment.
  89. 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

    Copy & paste the code below to embed this comment.
  90. 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[ i ]) && ! trs[ i ].style.backgroundColor) {
    trs[ i ].className = even ? “even” : “”;

    Copy & paste the code below to embed this comment.
  91. 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.
  92. 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?

    Copy & paste the code below to embed this comment.
  93. 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.

    Copy & paste the code below to embed this comment.
  94. 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[ i ].className==“stripedList”){
    var colorElements = allLists[ i ].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 >

    Copy & paste the code below to embed this comment.
  95. ‘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).

    Copy & paste the code below to embed this comment.
  96. This is evil:

    <body onLoad=“function()”>

    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.
  97. 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

    Copy & paste the code below to embed this comment.