Functino

My daily struggle with webdevelopment

Zebra Tables: How to alternate table row colors

What is a “Zebra Table”? It’s a striped table with alternating row colors like this:

A simple Zebra Table

A simple Zebra Table

You can achieve this with very different approaches:

CSS only

With CSS 3 you can achieve such a table with the pseudo class nth-child. The rules are extremly simple and no additonal markup is required. Just add these lines to your CSS:

tr:nth-child(even) {background-color: #FFF}
tr:nth-child(odd) {background-color: #FFCC00}

But since not all browsers understand this CSS 3 selector this is perhaps not the best solution.
Instead of relying on Browsers CSS 3 support you can also use JavaScript to achieve the same result.
There is a great article on the jQuery-Blog with examples for all major JS-Framework. Take a look: http://blog.jquery.com/2006/10/18/zebra-table-showdown/

Using PHP to add classes

If you don’t want to use the CSS-only or the JavaScript solution you can use one of the following solutions. The basic idea is to add classes to your rows that indicate if it is an even or an odd row. You can do this by adding an “odd” class to odd rows and an “even” class to even rows. Or if you want a more minimalistic approach: Just add an “altrow” class to odd rows. It could look like this:

Or:

<table>
  <tr>
    <!-- your tds go here //-->
  </tr>
  <tr class="altrow">
    <!-- your tds go here //-->
  </tr>
  <tr>
    <!-- your tds go here //-->
  </tr>
  <tr class="altrow">
    <!-- your tds go here //-->
  </tr>
</table>

And style it with CSS like this:

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

or

tr { background-color:#FFF; }
tr.altrow{ background-color:#FFCC00;}

So how do we add those class names with PHP. I assume we have the following array with animals and want to print them out to a table:

<?php
$animals = array("Dogs", "Cats", "Monkeys", "Frogs", "Kangaroos");
?>

You can use the modulo operator % to determine wether a row is even or odd:

<table>
<?php for($i = 0; $i < count($animals); $i++): 
    if($i % 2 == 0)
    {
      $class = "even";
    }
    else
    {
      $class = "odd";
    }
  ?>
  <tr class="<?php echo $class;?>">
    <td> <?php echo $animals[$i];?></td>
  </tr>
<?php endfor;?>
</table>

Or if we use the handy ternary operator:

<table>
  <?php for($i = 0; $i < count($animals); $i++): ?>
    <tr class="<?php echo ($i % 2 == 0) ? "even" : "odd";?>">
      <td> <?php echo $animals[$i];?></td>
    </tr>
  <?php endfor;?>
  </table>
Or if you use the "altrow" instead of "even" and "odd":
<pre lang="php"><table>
  <?php for($i = 0; $i < count($animals); $i++): ?>
    <tr <?php echo ($i % 2 == 0) ? '', ' class="altrow"';?>>
      <td> <?php echo $animals[$i];?></td>
    </tr>
  <?php endfor;?>
</table>

If you use classnames like “row_0″ and “row_1″ instead of even and odd it comes down to this:

<table>
  <?php for($i = 0; $i < count($animals); $i++): ?>
    <tr class="row_<?php echo ($i % 2);?>">
      <td> <?php echo $animals[$i];?></td>
    </tr>
  <?php endfor;?>
</table>

Instead of the modulo operator you can also use a simple bit operation like this:

<table>
  <?php for($i = 0; $i < count($animals); $i++): ?>
    <tr class="<?php echo ($i & 1) ? 'odd', 'even';?>">
      <td> <?php echo $animals[$i];?></td>
    </tr>
  <?php endfor;?>
</table>
 
If you don't need the row number ($i) you can also do something like this:
<pre lang="php">
<table>
  <?php $even = 0; 
  foreach($animals as $animal):
    $even = 1 - $even; ?>
    <tr class="<?php echo $even ? 'even', 'odd';?>">
      <td> <?php echo $animal;?></td>
    </tr>
  <?php endfor;?>
</table>

There is another solution with PHPs next() and reset() functions:

<table>
  <?php $classes = array("even", "odd");
  foreach($animals as $animal):
    $class = next($classes) or reset($classes); ?>
    <tr class="<?php echo $class;?>">
      <td> <?php echo $animal;?></td>
    </tr>
  <?php endfor;?>
</table>

With this solution you can also use more than two different styles like this:

<?php 
$colors = array("#f00", "#0f0", "#00f");
while(loopingThroughWhatever())
{
  $color = next($colors) or reset($colors);
  //use it somewhere
  echo $color;
}
?>

Or another simple example:

<?php
$class = "odd";
while(loopingThroughWhatever())
{
  $class = ($class == 'even') ? 'odd' : 'even';
}
?>

However I find it kind of annoying when I have to initalize $class evrytime. Well, if you don’t need both classes (even and odd) you can simply do something like this:

<?php
while(loopingThroughWhatever())
{
  $class = empty($class) ? 'odd' : '';
  //use it somewhere
  echo $class;
}
?>

With this last approach you can simplify things a lot. Take a look at this code generated by CakePHP’s bake generator:

<?php
$i = 0;
foreach ($animals as $animal):
        $class = null;
        if ($i++ % 2 == 0) {
                $class = ' class="altrow"';
        }
?>
<tr<?php echo $class;?>>

This would become something like this:

<?php foreach($animals as $animal):?>
  <tr <?php echo $class = empty($class) ? ' class="altrow"' : '';?>>

(Note that there is a little difference in the behaviour of this two: The latter one adds the altrow class to the first, third, fifth, … row while the first one adds the altrow class to the second, fourth, …)

I know there are other solutions out there and you can easily combine different approaches (for example use if(){} instead of the ternary operator ?:, or create a function, use a switch, etc… )). So what do you use?

In my next posting I’ll take a look at how this is handled in Smarty, Zend Framework, Rails and in CakePHP – and I’ll come up with my own CakePHP-Helper to achieve Zebra Tables.

« Previous post

7 ResponsesLeave one →

  1. Thanks a lot, for your perfect explanation of how to create this effect! I ended up doing another solution though,

    while($row = mysql_fetch_array($resultat))
    {
    ?> <tr class="row_”>
    <?php
    … … … …
    $i++;
    }

    worked good in my situation I guess. Thanks again!

  2. jayaprakash

     /  November 6, 2009

    sir,

    please let me know how to combine your logic with the tablecells function of cake php.

    the present code is

    tableHeaders(
    array(‘Code’, ‘Unit’, ‘IP Address’, ‘Email’,)
    );

    foreach($units as $unit) {

    $class = next($classes) or reset($classes);
    echo $html->tableCells(
    array(
    $unit['Unit']['code'],
    $unit['Unit']['name'],
    $unit['Unit']['ip'],
    $unit['Unit']['email']

    )
    );

  3. Andreas

     /  November 8, 2009

    Hi jayaprakash,
    if you already use cakePHPs tableCells-Helper you can use the oddTrOptions and evenTrOptions.
    It’s explained here:
    http://book.cakephp.org/view/841/tableCells

  4. Mark

     /  November 19, 2009

    Hello,

    Thank you for your great explanation! I do understand most of it, but can’t seem to get it to work in my case.

    I’m importing a CSV file, and that adds difficulty.

    This is my code;

    <?php
    print("\n”);
    $row = 0;
    $handle = fopen(“test_portfolio.csv”, “r”);
    while (($data = fgetcsv($handle, 1000, “,”)) !== FALSE) {
    $num = count($data);
    for ($c=0; $c <= $row; $c++)
    {
    print("”);
    print(“”.$data[0].” “);
    print(“”.$data[1].” “);
    print(“”.$data[2].” “);
    print(“”.$data[3].” “);
    print(“”.$data[4].” “);
    print(“”.$data[5].” “);
    print(“”.$data[6].” “);
    print(“”.$data[7].” “);
    print(“”);
    }
    }
    fclose($handle);
    ?>

    Do you have any idea how to achieve this zebra pattern with this? Thanks so much!

    Mark

  5. Mark

     /  November 19, 2009

    I made it work, thanks anyway!

  6. Andreas

     /  November 19, 2009

    Hi Mark,
    great you figured it out for yourself and sorry for the late reply. :)

  1. cakePHP cycle-helper: alternating row colors with cake « Functino

Leave a Reply