Dreamweaver has a Repeat Region server behavior that loops through your data and allows you to display it in a vertical or horizontal manner. If you want to display the data in a grid pattern, however, it requires a little more effort. Typically, a Horizontal Looper extension or code is used to create a table and put your individual data sections in a table cell. In this tutorial I'll show how to do that using <div> tags and CSS without tables. For this tutorial for PHP, I'll assume you know how to use MySQL tools to create and manage databases, and how to create connections for PHP in Dreamweaver.

Create a Sample Database and Connection

To continue with the tutorial you'll need some sample data. The included script will generate a sample table for you, or you can use any database you have at your disposal. Simply create a blank database (or use a test database) and run the northwindproducts.sql file included in this download. This will create the Products table from the Microsoft sample Northwind database, which is a common database that developers have at their disposal. If you would prefer to load in the complete Northwind database for MySQL you can find it at my site at http://www.flash-remoting.com/examples/frdg/northwindmysql.zip

After creating the table, you'll need a connection in Dreamweaver to continue. Create that now, and call it "connNorthwind".

Creating the Recordset

In the Bindings tab, create the recordset now using the Advanced dialog. In the dialog box for SQL, put the following SQL statement:

SELECT p.ProductID, p.ProductName, p.UnitPrice
FROM products p
ORDER BY p.ProductID

When you test, you should see all the records. Name the recordset rsLooper and click OK if everything tested OK.

Working in Design View

When you create the code, you can do it in code view or design view, however I'll do it in design view, as that speeds up the process if you have experience with it. Using the Layout tab of the Insert bar, insert a <div> tag. There is a button for Insert Div Tag and Draw AP Div. Make sure you use the Insert Div Tag button or the loop will not work. Put the cursor on the blank page and click the button to insert the tag. Choose to insert At Insertion Point and give the tag an ID of "looper".

Figure 1: Inserting a DIV

Click OK and you should see some sample content on the page, still selected. Without touching anything else and the text still selected, insert another div. This time, you won't need a class or ID, but the insertion will change to "Wrap Around Selection". That is exactly what we want, so click OK.

Next, with the text still selected, open the Bindings panel and expand the rsLooper recordset. You'll be dragging each field onto the page and replacing the selected text. First, drag the ProductID field to the page and drop it right on the selected text. It will replace it. Hit your right arrow key to unselect and move the cursor to the end of the line. Press Enter/Return after this. This will put you on a new line, still within the div. Next drag the ProductName field to the page. Do the same thing -- right arrow and then hit Enter to take you to a new line. Finally, drag the UnitPrice field to the page. Your page should now look like this:

Figure 2: The page after dragging the fields from Bindings

The code should look like this at this point:

<div id="looper">
    <p><?php echo $row_rsLooper['ProductID']; ?></p>
    <p><?php echo $row_rsLooper['ProductName']; ?></p>
    <p><?php echo $row_rsLooper['UnitPrice']; ?></p>

Put a <style> tag in the head and add some CSS to the inner divs so that we can see the results of what we are doing:

#looper div {
border:1px dotted red;

This will put a red border, a 150px width, and some space around the data and around each div within the #looper div. If you were to browse to the file now to check your progress, you would see one red-bordered div with one data record displayed. We'll need to use a repeat region next to repeat this data.

Repeat Region

We'll use the Repeat Region server behavior in code view next. Select the inner div completely and open the Server Behaviors panel. Choose the Repeat Region behavior. The default is to show all records, but we want to show only 9. 9 records will give us a 3 x 3 grid. We want to make our repeat count a multiple of whatever grid we decide on, so we would use 12 records for a 4 x 3 grid, 16 for a 4 x 4 grid, etc.

If you browse the page now, you'll see the divs repeated vertically on the page:

Figure 3: The data is repeated vertically at this point

To loop this data horizontally at this point, we simply have to insert a float in the CSS definition for the divs that we already created:


This will give us the following result:

Figure 4: The horizontally looped records

This is still not exactly what we want, because the floated divs float horizontally only as far as the browser is expanded, then wrap to the next line. We'll need to count 3 records and insert an element to break the flow. We can do this with the following tag:

<br style="clear:both" />

Getting it in the correct place is a bit tricky, but easy enough if you know the code.

Setting a Counter

To create the proper count, we need to set a counter at the top of the page:

<?php $loopCounter = 0;?>

This will initialize a counter. Next, inside the Repeat Region (in code view), add this line directly below the start of the loop but before the <div>:

<?php $loopCounter++; ?>

This will set the counter to 1 before the first row of data is shown, and increment itself before each record to whatever record number is being shown.

We'll use a modulo operator to create our break in the horizontal line. A modulo operator gives you a remainder of a division, so to test whether we have displayed 3 records, we test the modulo of $loopCounter and 3 to see if it is zero (no remainder). If so, we insert the <br/> tag, directly after the inner closing <div> but before the end of the loop:

<?php if($loopCounter % 3 == 0) echo('<br style="clear:both"/>');?>

The completed code now looks like this:

<div id="looper">
<?php do { ?>
  <?php $loopCounter++; ?>
    <p><?php echo $row_rsLooper['ProductID']; ?></p>
    <p><?php echo $row_rsLooper['ProductName']; ?></p>
    <p><?php echo $row_rsLooper['UnitPrice']; ?></p>
  <?php if($loopCounter % 3 == 0) echo('<br style="clear:both"/>');?>
<?php } while ($row_rsLooper = mysql_fetch_assoc($rsLooper)); ?></div>

If I were hand-coding, I might not use the opening and closing <?php ?> tags as often, but removing them creates confusion for Dreamweaver.

To change the number of cells in the grid, simply change this 3 to a 4, 5, or however many cells across your loop will display. Also remember to change the repeat region to a multiple of this number.

The page now displays our rows in a 3 x 3 grid:

Figure 5: The 3 x 3 horizontal looper grid

The Wrapper div

One thing you might notice is that if you squish your browser width to less than the width of the looped divs, they will start wrapping down below each other. This is due to the nature of floats, but can be avoided by simply giving the #looper div a width:

#looper {width: 800px;}

This width is larger than the 150px width of the individual cells, plus the margin, border, and padding, so the wrapping will not affect most users, unless they crank up their font size to astronomical proportions.

Adding paging

Finally, because we are using a basic repeat region, we can use Recordset Paging server behaviors to create the paging. This will also work with my Recordset Navigation Suite, for those users who have that set of behaviors.

First, insert another break after the looper div:

<br style="clear:both" />

This will make sure that if there is a partial row (the last page of data typically does not divide evenly by 3) there will be a break after the data display. Then, add the Recordset Navigation Bar (or similar behavior from the Recordset Navigation Suite.) The page will now be pagable, with First, Previous, Next, and Last links.


With the addition of a few simple lines of code to Dreamweaver's generated code, it is simple to create a horizontal looper without the use of a table.