Generating HTML Tables with a Variable Number of Columns and Rows

Often when you’re generating an HTML table on the fly, you need to be able to display an arbitrary number of columns and rows. This typically comes up when displaying data from a database, where you can get any number of records (rows) back. Fortunately handling a variable number of rows is easy in HTML, since all you have to do is keep adding table row tags until you run out of records. The harder, and less common, case is handling a variable number of columns. An example of where this situation comes up is my Shashin plugin, as Shashin users can decide how many columns they want in the display of their photos. Another example is a form where you need multiple rows and columns for neatly laying out a variable number of checkboxes.

I’ve seen a number of strange and tortured solutions to this problem over the years, so I thought I’d share my solution, which is really simple (I’m sure many others have figured this out as well, but I haven’t seen it posted anywhere). What’s often missing in other solutions I’ve seen is properly closing the final table row when the number of cells in it is less than the preceding rows. Here’s some generic PHP code for it:

// desired number of columns - this can be any number
$cols = 3;

$output = "<table>\n";

$cell_count = 1;

for ($i = 0; $i < count($your_array); $i++) {
    if ($cell_count == 1) {
        $output .= "<tr>\n";
    }

    $output .= "<td>your cell content</td>\n";
    $cell_count++;

    // end the row if we've generated the expected number of columns
    // or if we're at the end of the array
    if ($cell_count > $cols || $i == (count($your_array) - 1)) {
        $output .= "</tr>\n";
        $cell_count = 1;
    }
}

$output .= "</table>\n";

And just for fun here’s the same thing in Smarty:

<table>
<{assign var="cell_count" value=1}>
<{foreach key=key item=item from=$your_array name=yourloop}>
    <{if $cell_count == 1}>
        <tr>
    <{/if}>
    <td>your cell content</td>
    <{math assign="cell_count" equation="$cell_count + 1"}>

    <{if $cell_count > 3 || $smarty.foreach.yourloop.last}>
        </tr>
        <{assign var="cell_count" value=1}>
    <{/if}>
<{/foreach}>
</table>

3 Comments

  1. Reply
    Pat W March 5, 2008

    Wrap images in a div.

    div {
    float:left;
    padding:0 5%;
    }

    Increase the side padding to have fewer images per row. 🙂

  2. Reply
    Mike March 5, 2008

    But does that work when the heights and widths of the images vary? (e.g. some portrait, some landscape). Long live tables! 😉

  3. Reply
    Pat W March 6, 2008

    It would work with widths but you do have to add some logic to insert padding to even out the heights unfortunately.

    It looks much simpler thought 😉

Leave a Reply