Multiple Content Areas

This post has been marked as old. The code might no longer work. Comments have been disabled as this is no longer maintained. Use the search on the right to find a newer tutorial.

I’m closing the comments on this as it’s a very old technique that I no longer use or recommend. A much better option is to use Column Classes in your CSS file, then use the Div Shortcode Plugin to make it easy to create columns in your pages.

WordPress works great if you want to display a title and then a block of content, but if you’re using it as a CMS you’ll often be faced with the problem of multiple content areas. You might need multiple boxes on a homepage, or 3 columns of text on an inner page.

There’s many ways to go about this. Some of them include:

  • Including <div>‘s in your post content. This will work well for a developer who understands code, but for clients it is not usually a good option. They will typically work in the Visual mode, and can easily delete or break the<div>‘s, then not know how to add them back in HTML mode.
  • Using sidebars and widgets to display content. This is good for one-off things like sidebars (same across the site) or boxes on a homepage (only used once), but it doesn’t scale well – you don’t want 20 different sidebars for different areas of your site. It also disconnects the content from the page. It’s nice to have all the content that will appear on a page editable in the same place. (This goes back to my principle of making client’s sites easy to use and hard to break).
  • Using a shortcode to break content up into multiple columns. Ex: [column id=”1″] text in column 1 [/column] [column id=”2″] text in column 2[/column]. I think this is a great solution, but the solution outlined below is a little easier for  non-technical people to use.
  • Adding an additional WYSIWYG meta box to the page editor for the second column. Again, this is a good solution but I believe the one outlined below is easier. The solution below also allows you to determine the number of columns on a per-page basis rather than a per-site basis like a meta box.

For a project I’m working on now we needed two or three columns of content on every page (here’s an example on the client’s site). All the blocks of content are unique to that page. This solution was inspired by a post at kriesi.at, but I’ve modified it with the help of Chris Bratlien to make as many content areas as you like (the code from that post only creates a left column and a right column).

The Content

When you’re writing your content in WordPress, simply break up the content sections using an <h4> heading. I chose <h4> because it’s easily accessible from the menu bar. Select the text you want as your heading, click on the last icon in the menu( )  then click where it says Paragraph and go down to Heading 4. You could change this to whatever heading you’d like; I chose Heading 4 because for this project we only used <h1>, <h2> and <h3>.

The Code

In your functions.php file (custom_functions.php file for Thesis), paste the following code:

add_filter('the_content', 'multi_content');
 function multi_content($content){
 $columns = explode('<h4>', $content);
 $i = 0;
 foreach ($columns as $column){
 $return .= "<div class=\"column\" id=\"content-$i\">" . "\n";
 if ($i > 1) $return .= "<h4>";
 $return .= $column;
 $return .= '</div>';
 $i++;
 }
 if(isset($columns[1]))
 $content = wpautop($return);
 else
 $content = wpautop($content);
 return $content;
}

Here’s what that is doing:

  • $columns = explode('<h4>', $content); Break up the content into separate blocks every time you find an <h4>.
  • $i = 0; Make a counter (called i) and start at 0.
  • foreach ($columns as $column){ For every block of content…
  • $return .= "<div class=\"column\" id=\"content-$i\">" . "\n"; Add a div with the class of “column” and the id of “content-[i]”, so content-0, content-1…
  • if ($i > 1){$return .= "<h4>";} If this is any block of content except the first, add back the <h4> (our first block of content was everything before the first <h4>, so we don’t want to add an additional one)
  • $return .= $column; $return .= '</div>'; $i++;} Add the block of content and close the div at the end. Then move the counter up one and start again.
  • if(isset($columns[1])) $content = wpautop($return); If there’s only one block of content (no <h4>‘s were used), ignore everything we did and just show the content.
  • else $content = wpautop($content);  return $content; } If there was more than one block of content, replace the default WordPress content with the div’s and content we just did.
  • add_filter('the_content', 'multi_content'); Run this filter every time WordPress wants to see the content of a post or page.

You’ll then need to add the appropriate css to make it behave as you like. If you want to apply css to all the columns, use the class “column.” If you want to add css to individual columns, use their id’s. Here’s an example:


.column {float: left;}
#content-0 {width: 400px;}
#content-1 {width: 300px;}

I hope that helps some of you. I know I will be using it a lot for client websites.

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson

Comments

  1. Don says

    Hi.

    I can’t get this to work on my site (WP 3.1 and newest Thesis version)

    I have setup things exactly as described and I can see that the correct ‘s are inserted in the code.

    In the custom.css file I have inserted the lines below but nothing changes on my pages. (I have double checked that custom css is enabled in Thesis!).

    .custom .column {float: left;}
    .custom #content-0 {width: 400px;}
    .custom #content-1 {width: 150px;}
    .custom #content-2 {width: 150px;}

    I hope someone can help me out.

  2. Tom says

    Thanks for code! But I found mistake. At the 7th line of code it should be ” if ($i > 0) $return .= “”;” instead of what is now. Of course I you use only columns in your content.

  3. Lynne Good-Miller says

    I would like to use this for a page template – maybe using if ( is_page_template(‘3coltemplate.php’)) {

    I am having some problems – how would I incorporate this if I only want it executed if I use a certain page template?

    Thank you so much!

    • Bill Erickson says

      Modify this line:

      if(isset($columns[1]))

      To this:

      if( isset( $columns[1] ) && is_page_template( '3coltemplate.php' ) )

  4. Lynne Good-Miller says

    Actually – I just put the code on the page template itself and it works – is that the best way to do it if I only want it when certain templates are used?

    • Bill Erickson says

      Either way should work. Your way is probably best since it keeps all that template’s code in a single file, but my approach would work regardless of your template structure (I can’t advise on how to modify your code without seeing it, so I had to modify mine)

  5. robert says

    Fantastic solution to WP columns.
    But I’m having problems, could you have a look?

    WP 3.2.1 / Thesis 1.8

    In custom.css
    .a-test-columns .column {width: 30%; float: left; padding-right: 10px;}
    .a-test-columns #content-1 {width: 175px;}
    .a-test-columns #content-2 {width: 175px;}
    .a-test-columns #content-3 {width: 175px;}

    In custom_functions.php
    add_filter(‘the_content’, ‘multi_content’);
    function multi_content($content){
    $columns = explode(”, $content);
    $i = 0;
    foreach ($columns as $column){
    $return .= “” . “\n”;
    if ($i > 1) $return .= “”;
    $return .= $column;
    $return .= ”;
    $i++;
    }
    if(isset($columns[1]))
    $content = wpautop($return);
    else
    $content = wpautop($content);
    return $content;
    }

    http://www.graphics-i-design.com/a-test-columns/
    Column 1
    Test column 1Test column 1Test column 1Test column 1Test column 1Test column 1Test column 1Test column 1Test column 1Test column 1Test column 1.

    Column 2
    Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2

    Column 3
    Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2Test Column 2

    Any comments very appreciated, I like your solution to WP columns.
    -robert