I’ve been working on a WordPress site for a client with one of our developers Tom Hartnell. The design of this particular site was that some pages would need content displayed over multiple columns. This content had to be updatable by the client, as such it could not be hard coded into the template files.
We had a look around and we found a potential solution on this blog post.
We played around with this for a while but found that, whilst it was a good solution, it wasn’t quite suitable for our needs. What we needed was a solution which allowed us to have any number of columns and for each column to contain completely different content. The solution in the post demanded that each column start with the same HTML tag (H2 in the example). We decided to rewrite the function described above, based on the same principals, but updated and improved so it would fit our needs.
To see what the end result is, you can see a demo page.
The first thing the new function had to do was to split the content into the different columns using the more tag. In our tests, we found that WordPress replaced the more tag with a span, but only in the first instance, all the rest were kept as a comment tag. The regular expression we used had to take this into account.
// the first "more" is converted to a span with ID $columns = preg_split('/(<span id="more-d+"></span>)|(<!--more-->)</p>/', $content); |
This regular expression is not bullet proof, but it does the job for us. Specifically, if you are using a plugin like “Sociable” or something that appends stuff to the end of the content then this stuff will end up in the third column and not nicely across the bottom of the page. Also, it hasn’t been tested when adding images. These two issues weren’t going to be a problem for us, so the regular expression above is perfectly adequate for our needs.
Next we need to loop through each column, removing any stray <p> tags that may have been orphaned by the regular expression and putting the content into separate divs.
$col_count = count($columns); for($i=0; $i<$col_count; $i++) { // check to see if there is a final, if not add it if(!preg_match('/</p>s?$/', $columns[$i]) ) { $columns[$i] .= '</p>'; } // check to see if there is an appending, if there is, remove $columns[$i] = preg_replace('/^s?</p>/', '', $columns[$i]); // now add the div wrapper $columns[$i] = '<div class="dynamic-col-'.($i+1).'">'.$columns[$i].'</div>'; } |
Finally we can join the columns back together to produce the final content.
$content = join($columns, "n").'<div class="clear"></div>'; |
Notice that we have added a clearing div here. This is basically so you can clear the floats with CSS so any content displayed below the page content will be correctly positioned.
What if there isn’t a more tag? We will only have one column. As such there is no need to modify the content, so the code above should go into an if statement
if($col_count > 1) { ... } |
The last job to do in this function is to clear out any blank <p> tags caused by the regular expression and return the content
// remove any left over empty tags $content = str_replace('<p></p>', '', $content); return $content; |
This would normally all be contained in a function (we called my_multi_col_v2) that would be called as a filter function, however, we found that this was causing problems with the WordPress excerpts, so instead we are overriding the default content display function in the page.php file.
In your page.php file, replace the line that calls the the_content() function
//the_content('Read the rest of this entry »'); |
Now we collect the content into a variable, then pass this variable to the new function, outputting the result. The function that gets the content instead of directly outputting it is get_the_content():
$content = get_the_content('',FALSE,''); //arguments remove 'more' text echo my_multi_col_v2($content); |
As we are using get_the_content() the default filtering that is normally done on the content is not being run. So at the top of our new function, we must manually run these
// run through a couple of essential tasks to prepare the content $content = apply_filters('the_content', $content); $content = str_replace(']]>', ']]>', $content); |
This also caused a problem with line breaks when only displaying one column, so we needed to include an else statement that ran wpautop()
else { // this page does not have dynamic columns $content = wpautop($content); } |
So the final function looks like this:
function my_multi_col_v2($content){ // run through a couple of essential tasks to prepare the content $content = apply_filters('the_content', $content); $content = str_replace(']]>', ']]>', $content); // the first "more" is converted to a span with ID $columns = preg_split('/(<span id="more-d+"></span>)|(<!--more-->)</p>/', $content); $col_count = count($columns); if($col_count > 1) { for($i=0; $i<$col_count; $i++) { // check to see if there is a final </p>, if not add it if(!preg_match('/</p>s?$/', $columns[$i]) ) { $columns[$i] .= '</p>'; } // check to see if there is an appending </p>, if there is, remove $columns[$i] = preg_replace('/^s?</p>/', '', $columns[$i]); // now add the div wrapper $columns[$i] = '<div class="dynamic-col-'.($i+1).'">'.$columns[$i].'</div>'; } $content = join($columns, "n").'<div class="clear"></div>'; } else { // this page does not have dynamic columns $content = wpautop($content); } // remove any left over empty <p> tags $content = str_replace('<p></p>', '', $content); return $content; } |
The next thing to do is to update your CSS so it lays out the columns correctly. In the demo I have used three columns, and the CSS for it looks like this:
/* dynamic columns */ div.dynamic-col-1 { float: left; width: 38%; padding-right: 2%;} div.dynamic-col-2 { float: left; width: 38%;padding-right: 2%;} div.dynamic-col-3 { float: left; width: 20%;} div.clear { clear: both; } |
And that’s pretty much it. Have a look at the demo, below is a screenshot of the WordPress editor screen so you can see that it really is controlled by the user, you should see the two more tags that are used to split the content into the three columns.
Please feel free to take this, improve it, update it, completely rewrite it. If you do please can you drop me a comment and let me know. And a big thanks to Kriesi for his initial work and for providing inspiration for this blog post.

Pingback: Rob Searles » Wordpress: Multiple Content Columns
Pingback: Rob Searles » Wordpress: Multiple Content Columns
Pingback: Twitter Weekly Updates for 2009-12-20
Pingback: Nga
Pingback: Derosa
Pingback: 6 Ways to Display WordPress Post Content in Multiple Columns | Digging into WordPress