Better WordPress Archives via Dynamic Triple Column Layout

[ ~{*}~ ] Here at Perishable Press, the number of posts listed in my archives is rapidly approaching the 700 mark. While this is good news in general, displaying such a large number of posts in an effective, user-friendly fashion continues to prove challenging. Unfortunately, my current strategy of simply dumping all posts into an unordered list just isn’t working. I think it’s fair to say that archive lists containing more than like 50 or 100 post titles are effectively useless and nothing more than a usability nightmare. With growing numbers of blogs building up massive collections of posts, finding better ways to display vast quantities of archived material becomes increasingly important.

One solution that seems popular involves breaking the archives down into various categories, tags, and time periods. This provides meta-context to each list of titles and usually eliminates the need for any hideously long post listings. This solution works well, especially when the different category lists are displayed adjacently in multiple vertical columns. For example, a blog with three categories would do well to display each category’s archive listings in its own vertical column. Something like this:

[ Screenshot: Triple Archive Columns ]
Hypothetical Archive example showing posts listed in three category-specific columns

This is a much more convenient presentation of content because it enables users to browse larger portions of content with less effort. Such layout also fosters understanding of the site’s overall three-category structure, as well as providing visual cues as to the amount of content available in each category relative to the others. Further, using multiple columns to display lists of archive content results in an aesthetically fuller and richer-looking page. Rather than an awkward left-aligned list that descends endlessly down the page, we balance the composition efficiently with an appearance of order, fullness, and completion.

We may also apply this reasoning to the display of all archived posts. Instead of just dumping a million posts into a single, left-aligned list, let’s create a couple of extra columns, divide our posts evenly among them, and restore a sense of harmony to our site’s Archive page. To do this, we must embrace the magical powers of CSS, (X)HTML, PHP, and of course WordPress.

By default, WordPress provides a way to list all of our posts using the “wp_get_archives()” template tag, parameterized as follows:

<?php wp_get_archives('type=postbypost&limit='); ?>

Many sites use this method to display their entire collection of posts on their site’s Archive page. This certainly does the job, but unfortunately does not allow us to implement the improved, three-column layout discussed above. To accomplish this, we need a way to divide the archive post list into three sections, such that an even (or similar) number of posts are available to each of our three columns. As far as I know, there is no “built-in” way to acheive this with WordPress, but it is easily accomplished using a bit of customized functionality. ;)

At this point, you may be thinking that multiple loops are the way to go. If so, you are partially correct. For any known number of posts, we may easily configure a triple-loop script to display all of our posts. For example, if we know we have 300 posts to display, we can write this and be done with it:

<div id="column-01">
   <ul>
      <?php query_posts('showposts=100&offset=0); ?>
      <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

      <li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>

      <?php endwhile; endif; ?>
   </ul>
</div>
<div id="column-02">
   <ul>
      <?php query_posts('showposts=100&offset=100); ?>
      <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

      <li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>

      <?php endwhile; endif; ?>
   </ul>
</div>
<div id="column-03">
   <ul>
      <?php query_posts('showposts=100&offset=200); ?>
      <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

      <li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>

      <?php endwhile; endif; ?>
   </ul>
</div>

For fixed post quantities, this technique works perfectly, displaying 100 posts in each of our three columns. Each column is uniquely identified and includes its own customized loop. Each loop is customized via the query_posts() function, which utilizes its showposts and offset parameters to modify loop behavior. The showposts parameter remains the same in each loop, however the offset parameter begins at zero and increases by increments of 100 to prevent duplicate post display. So far so good..

The “real-world” problem, of course, is that the total number of posts generally changes frequently, making it necessary to continually edit the query_posts() parameters to ensure proper archive display. Thus, for the triple-loop solution to work effectively and efficiently, we need to automate the process by using dynamically assigned parameter values. Fortunately, this is easily accomplished using some built-in WordPress functionality and a bit of “hand-rolled” PHP:

<?php // calculate triple-column post-display variables
// http://perishablepress.com/press/2009/02/10/better-wordpress-archives-via-dynamic-triple-column-layout/

// get published post count in WordPress 2.5+
$count_posts = wp_count_posts();
$numposts = $count_posts->publish;

// number of posts in columns one and two
$columnOneTwoPosts = round($numposts / 3);

// number of posts in column three
if(3*$columnOneTwoPosts < $numposts) {
	$columnThreePosts = $columnOneTwoPosts + 1;
} elseif(3*$columnOneTwoPosts > $numposts) {
	$columnThreePosts = $columnOneTwoPosts - 1;
} elseif(3*$columnOneTwoPosts == $numposts) {
	$columnThreePosts = $columnOneTwoPosts;
}

// post offset for column one
$columnOneOffset = 0;

// post offset for column two
$columnTwoOffset = $columnOneTwoPosts;

// post offset for column three
$columnThreeOffset = 2*$columnOneTwoPosts;

?>

This script dynamically assigns values for our showposts and offset parameters, based on the current total number of posts. Following along with the comments included in the code, we see that the script first determines the total number of posts using WordPress’ relatively new wp_count_posts() function*. The script then mathematically manipulates the total post value until the following variables have been assigned:

  • $columnOneTwoPosts — provides the showposts parameter with the number of posts displayed in the first and second column
  • $columnThreePosts — provides the showposts parameter with the number of posts displayed in the third column
  • $columnOneOffset — provides the offset parameter for the first column
  • $columnTwoOffset — provides the offset parameter for the second column
  • $columnThreeOffset — provides the offset parameter for the third column

Once this script has been included in your Archive page, seal the deal by editing the previously discussed triple-loop configuration with the newly established variables:

<div id="column-01">
   <ul>
      <?php query_posts('showposts='.$columnOneTwoPosts.'&offset='.$columnOneOffset); ?>
      <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

      <li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>

      <?php endwhile; endif; ?>
   </ul>
</div>
<div id="column-02">
   <ul>
      <?php query_posts('showposts='.$columnOneTwoPosts.'&offset='.$columnTwoOffset); ?>
      <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

      <li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>

      <?php endwhile; endif; ?>
   </ul>
</div>
<div id="column-03">
   <ul>
      <?php query_posts('showposts='.$columnThreePosts.'&offset='.$columnThreeOffset); ?>
      <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

      <li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>

      <?php endwhile; endif; ?>
   </ul>
</div>

And done! Nothing needs to be edited, updated, or configured — ever!! With this triple-column method in place, your Archive page will now feature a well-balanced, three-column post-listing of your entire collection of articles. By evenly dividing your total post number and calculating the proper offset values, the script ensures that all posts are displayed without any duplicates. Best of all, the three columns will always be within one line of the same size, regardless of the total number of posts.

* Notes

There are several ways to retrieve the total number of posts from WordPress. Currently, the triple-column script employs the wp_count_posts() function to get this information, however this function is not available in versions of WordPress older than 2.5. Thus, you will want to use the “classic” method of getting the total post count for older versions. To do so, replace the following lines:

// get published post count in WordPress 2.5+
$count_posts = wp_count_posts();
$numposts = $count_posts->publish;

..with these:

// get published post count in old WordPress versions < 2.5
$numposts = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_status = 'publish'");
if (0 < $numposts) $numposts = number_format($numposts); 

Further, if you are running WordPress 2.5 or better and PHP 5, you may use this shortcut in place of the current function:

// PHP5 shortcut for published post count in WordPress 2.5+
$numposts = wp_count_posts()->publish;

Also, if you want to display only the number of posts specified in the WordPress Admin Options settings, you may use this fine little function:

$numposts = get_option('posts_per_page');

And finally, to specify a custom number of posts to display, simply use this:

$numposts = 15;

Get out

As always, any suggestions, questions, or comments are welcome! Is there an easier way to achieve dynamic triple-column post display? Perhaps using only CSS? Some other WordPress function? Black magic? Chime in and contribute your knowledge!