Vertically Aligned Multi Column List Items

I was working with a client on a Drupal site and he wanted a multi column list. The big question of course is "Does the sort order matter?" Making a multi column list that's easily editable in a CMS is no problem as long as the sort order doesn't matter (or rather, as long as you do it horizontally). In fact, even if the sort order matters, you can use a grid view in Drupal and just deal with a table. There's a great article on A List Apart that talks about doing this with list items all in depth, but for any developer that runs across it scanning for how to do it programmatically in a CMS, you're out of luck.

The issue is that if you do it with a table, the height will be set by the largest column for each row. If your list item is multiple lines, it's pretty ugly. So how do you do this in Drupal with a view that uses an HTML list? Hack the view template of course. Here's the quick and dirty compromise we came up with: take the number of results, divide by 2. Put the first half in one unordered list, put the other half in the other. Below is the modified drupal views template with comments. While this is a Drupal solution, the logic behind it should be easy to implement in anywhere.

<?php
/* views-view-list.tpl.php
  make sure to rescan your templates in the theme information if you want this to only apply to more specific views...
*/
?>

<div class="item-list">
<?php
//the number of items to display is equal to the number of rows divided by two.  Round it just incase it's an odd number.  In the case of an odd number, we want it to make the first column bigger.

$itemsToDisplay = round(count($rows)/2);

?>

  <?php if (!empty($title)) : ?>
    <h3><?php print $title; ?></h3>
  <?php endif; ?>

<!-- $options spits out whether it's an UL or OL.  I add a class called col1 just in case I need to hit it directly with a style -->
  <<?php print $options['type']; ?> class="col1">
    <?php foreach ($rows as $id => $row): ?>

<!-- Now we check and see if we've gone through half of the list, if we have, we just ignore it until the for loop ends -->
  <?php if ($itemsToDisplay >= $id): ?>
      <li class="<?php print $classes[$id]; ?>"><?php print $row; ?></li>
  <?php endif;?>
    <?php endforeach; ?>
  </<?php print $options['type']; ?>>

<!-- Now we do the loop again, I know, not that efficient -->
  <<?php print $options['type']; ?> class="col2">
    <?php foreach ($rows as $id => $row): ?>
<!-- This time, we check the opposite, we want to know if the last half of the list. -->
  <?php if ($itemsToDisplay < $id): ?>
      <li class="<?php print $classes[$id]; ?>"><?php print $row; ?></li>
  <?php endif;?>
    <?php endforeach; ?>
  </<?php print $options['type']; ?>>

</div>

Add new comment