MSBware :: Logic Governing Design
T_main_tl T_main_tr

Articles

Article Options  
Icon_back Back to List
Icon_comment Post Comment

Categories  
Icon_listitem MySQL
Icon_listitem PHP
Alternating Row Colors
Icon_listitem Scripts

Alternating Row Colors

Written By Michael on Mar.06.2007

This concept is used all over the internet.  Almost every database driven website uses alternating row colors when displaying a list of records.  You've seen it used, you like it, and now you want to do it yourself.  But, you're not sure how to accomplish it.  Well you've come to the right place.  I'm going to discuss the basic idea behind achieving this and give some concrete examples demonstrating different ways to implement it.

First and foremost, we need a loop.  For now, we'll just use a for loop.

<?php
  
for ($k 0$k 5$k++)  {
    // Do something
  }
?>


Now we have some code that will execute 5 times.  Let's say each execution of this code prints a row of data.  We want the background color of the data to alternate between white and light grey.  Therefore, we need to define our colors.  One way to do that is through PHP:

<?php
  $bg1 
"#ffffff";   // White
  $bg2 "#ededed";   // Light grey
?>


The other is through a style sheet (and is the preferred method).  This is the method I will be using throughout this article.

<style>
  div.bg1  {  background-color: #ffffff;  }   // White
  div.bg2  {  background-color: #ededed;  }   // Light grey
</style>


Okay, so we have our colors.  Now how do we get them to alternate?  There's two main ways to accomplish this: using remainder division and using negation.  First up, remainder division:

<?php
  
for ($k 0$k 5$k++)  {
    if ($k == 1)    // L1: This is where the alternating row colors
      $class "bg1";   //     takes place.
    else                //
      $class "bg2";   // 
    
    
echo "<div class='".$class."'>Row ".$k."</div>";
  }
?>


Which will give us something like the image to the right.  Pretty simple.  If we wanted to have the first row white instead of grey, then all we would have to do is swap the colors in bg1 and bg2.


The 4 lines labeled L1 can be further condensed into one line using a ternary operator as demonstrated below.  If you've never seen this operator before, check out Unary, Binary, and Ternary Operators for an explanation.

<?php
  $class 
= ($k == 1) ? "bg1" "bg2";
?>


The second way to accomplish this is negation.  To do this, we first need a boolean variable.  When that variable is true, then we will display bg1.  When it's false, we'll display bg2.  Each loop, we'll negate the boolean variable so it we will use the other color on the next iteration.  Observe.

<?php
  $b 
true;   // Boolean variable
  
  
for ($k 0$k 5$k++)  {
    $class = ($b) ? "bg1" "bg2";
    $b = !$b;   // Negate the boolean variable
       
    
echo "<div class='".$class."'>Row ".$k."</div>";
  }
?>


You may ask: well, what about while loops?  The negation example works great for while loops without any additional code needed.  However, if you choose to use the remainder division technique, then you will need to add a counter variable as demonstrated below:

<?php
  $k 
0;   // Counter variable

  while ($k 5)  {
    $class = ($k == 1) ? "bg1" "bg2";
    $k++;

    echo "<div class='".$bg."'>Row ".$k."</div>";
  }
?>


You might be asking yourself: well, if there's two techniques, one has to be better, right?  In most cases, that is true.  However, in this situation, it really comes down to a matter of prerference.  I thought that the remainder division method would be slower since the remainder calculation takes more steps than a simple negation.  In order to know this for certain, I set up a little test on this server to see what would happen.  I used the following 6 snippets in my testing with the results posted below the code.

<?php
  
// TEST1: FOR - Control
  for ($k 0$k 10000000$k++)  {
    $class = (1) ? "bg1" "bg2";
  }

  // TEST2: FOR - Remainder division
  for ($k 0$k 10000000$k++)  {
    $class = ($k == 1) ?"bg1" "bg2";
  }
  
  
// TEST3: FOR - Negation
  $b true;
  for ($k 0$k 10000000$k++)  {
    $class = ($b) ? "bg1" "bg2";
    $b = !$b;
  

  // TEST4: WHILE - Control
  $k 0;
  while ($k 10000000)  {
    $class = (1) ? "bg1" "bg2";
    $k++;
  }

  // TEST5: WHILE - Remainder division
  $k 0;
  while ($k 10000000)  {
    $class = ($k == 1) ?"bg1" "bg2";
    $k++;
  }
  
  
// TEST6: WHILE - Negation
  $k 0;
  $b true;
  while ($k 10000000)  {
    $class = ($b) ? "bg1" "bg2";
    $b = !$b;
    $k++;
  
?>


Test Type Average Execution Time
TEST1 For - Control 7.36 seconds
TEST2 For - Remainder division 10.66 seconds
TEST3 For - Negation 12.74 seconds
TEST4 While - Control 7.20 seconds
TEST5 While - Remainder division 10.46 seconds
TEST6 While - Negation 12.19 seconds

That was definitely not what I expected.  It looks like the remainder division is the faster of the two.  It also appears that a while loop is the faster way loop through the same code.  However, it must be noted that this was for 10 million iterations.  If you were displaying that many rows in the browser window, you'd have alot more to worry about than which method was the faster way to choose the next row's background color.  Furthermore, the difference in execution times on more reasonable sets of data is negligable at best.  Therefore, I leave it up to you to decide which method you like best.  Both will get the job done equally well.

I hope this has helped you understand the methodology behind alternating row colors.  Please post your thoughts below and let me know what you thought of this article!

Comments

andris said on May.03.2007 1:47 AM...

XOR: $class = ($k ^ 1) ? "bg1" : "bg2";
Bert said on May.03.2007 12:50 PM...

Nice and simple. I especially appreciate how you took the time to benchmark the different methods to see which was more efficient, even if the differences would be negligible in most practical applications.
Matt said on May.03.2007 3:55 PM...

Add andris method to the benchmark. I bet it's fastest.
The True Slim Squirrel said on May.03.2007 6:51 PM...

This article is sassy, thanks. ALALALALALALALA!!!!
Michael said on May.03.2007 7:01 PM...

Matt and andris:

Thanks for the suggesion. I haven't ever used that bitwise operator to do this and I can't seem to make your code function correctly. If you can point out what I need to do, I'll rerun the benchmark using your code.

<?php
for ($k 0$k 5$k++)  {
  
$class = ($k 1) ? "bg1" "bg2";
  echo 
"class: ".$class."<br />";
}
?>


Outputs:
class: bg1
class: bg2
class: bg1
class: bg1
class: bg1
Fry said on Jun.09.2007 2:11 PM...

The XOR expression will not work as intentioned. I would think that andres wanted to check for the last bit in the counter value, as it will be 1 for odd values and 0 for even ones.

It will however work if we use the bitwise AND operator instead as in:

<?php
  
for ($k 0$k 5$k++)
    echo ((
$k 1) ? 'bg1' 'bg2') . '<br />';
?>


Happy coding! / Fry
Yash said on Aug.18.2007 2:44 PM...

Hey nice tutorial.But It doesn't conatin info abt mysql bolean..


Post Your Comments

* indicates a required field
*Your Name:
Your Email Address:
Your email address will not be posted anywhere on this site and will not be sold or given to anybody.
*Comments:

You can use the following to highlight your php code (be sure to include
the <? ?> tags!)

[CODE]
(code goes here)
[/CODE]


Enter the phrase below into the text box. This is for security reasons.


Reload captcha image
     






Valid XHTML 1.0

Powered by:
Powered by Symfony

PHP5 Powered
T_main_bl T_main_br