How to Display WordPress Posts in 2 or 3 Columns

Hello!

This is more advanced but I was wondering if you could do a PHP tutorial on how to split posts into two or three columns on the home page? Kind of like: http://www.happyindulgencebooks.com/

Thank you!

I’m going to do my best to answer this question, but it’s hard because I can’t give a “one solution fits all” answer. The code I provide here will have to be changed and adapted for your own theme. Everyone’s theme is slightly different, so all I can really do is give a generic response and hope that people reading this are able to change it to suit their own themes!

What we’ll be doing

Before

One column post layout

After

Two column post layout

What you see above in “after” is the roughest mockup ever. Sorry.

Requirements

If you’re going to attempt this, I advise the following:

  • You are using a custom theme or a custom child theme. In other words, your theme won’t have an “update” that will then delete all your changes.
  • You feel at least somewhat comfortable poking around theme files.
  • You don’t have to KNOW PHP, but you do have to be comfortable working around it and copying/pasting lines of PHP code.
  • You have FTP access to your blog so you can edit the theme files if you make a mistake and your blog becomes inaccessible because of a PHP error.

Step #1: Create column CSS

In order to do this, you need to have some CSS column classes in place. Your theme may already have these, or you may have to make them yourself. But basically what you need is a CSS class that acts as a column. Here’s one example for a two-column (so two posts side-by-side) layout:

.half {
	width: 50%;
	float: left;
}

The key thing is in the width. Since I want two columns, I need my div’s width to be half of 100%, which is 50%. If you wanted three columns, you’d need to set the div to one third of 100, which would be 33.3%.

Note: you can name the div whatever you want. I chose “half” just as an example. In order to avoid conflicts, it might be better to prefix it with something, like: ng-half (I chose “ng” here for “Nose Graze”).

Next, we need a div to wrap around the columns and clear the float. For this example, I’ll use:

.ng-row {
	clear: both;
}

Step 2: Finding your theme’s code for the homepage posts

The next step is finding the right file in your theme that outputs the code on the homepage for displaying your posts. In most themes this is the index.php file. However, some themes may have a different structure. For example, in the themes I code, I do have an index.php file, but in that file I tell it to include a separate file, which is where I keep the post code. I call that file loop-archive.php.

Now inside that file, you want to find a very specific block of code:

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>

[..]

<?php endwhile; ?>

There will be a lot of code in between, but you need to find the bit starting with the if (have_posts()) : while (have_posts()) : the_post(); portion. It may look slightly different from theme to theme, so look carefully. Then you need to find the end bit, which will be <? endwhile; ?>. We’re going to be working in and around this snippet.

This portion of the code is called The Loop. What it does is basically cycle through your WordPress posts. Everything inside that snippet is repeated for each individual post on your homepage.

Step 3: The column code

a) The easy way (may be glitchy)

There is an “easy” way to do this. Right after this line:

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>

Add this code:

<div class="half">

(or whatever your class name was)

And right before this line:

<?php endwhile; ?>

Add this code:

</div>

In the end, your code should look like this:

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div class="half">

[..]

</div>
<?php endwhile; ?>

With the rest of your theme’s code where the [..] bit is. You’re basically just wrapping your posts inside that column div. However, if your posts have varying heights, this could have some weird, unexpected results. There is a more complex method that is a lot more reliable…

b) The more advanced way

The more advanced way looks something like this:

<?php $i = 0; ?>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>

<?php
if($i == 0) {
	echo '<div class="ng-row">';
}
?>

<div class="half">

[..]

</div>

<?php
$i++;
if($i == 2) {
	$i = 0;
	echo '</div>';
}
?>

<?php endwhile; ?>

<?php
if($i > 0) {
	echo '</div>';
}
?>

Basically what we’re doing it starting a counter inside the code. We start the count at 0, then begin cycling through the posts. The first step is: if the counter is 0, add the div class for a new row. Then, after that, we insert the div class for a column (<div class="half">), and make sure the rest of the post display stuff from your theme is in there, before closing the div. Then, at the end, we increase the counter by one (so it’s now 1). However, then we need to perform some checks to determine if we should close the row div. Since we want two columns, we say: if the counter is 2, reset the counter to 0, then close the row div.

Once that’s done, The Loop (cycling through the posts) ends with <?php endwhile; ?> But what happens if the loop ends when the counter is only at 1? We won’t have closed the row div! So, we perform one final check at the end: if the counter is greater than 0, close the row div.

And that’s it!

If you’re not familiar with coding, I know this can look kind of confusing and intimidating.. especially if you’ve never seen/touched much PHP before. And since all themes have slightly different structures and layouts, it’s hard to have a “one size fits all” solution. Ultimately, you have to just try to apply the same logic to the theme that you have.

Just change the values for different numbers of columns

If you’re able to get it working with two columns, you can even try making it work with any number! You just have to change the values in the CSS (the div width) and in the PHP counter.

Photo of Ashley
I'm a 30-something California girl living in England (I fell in love with a Brit!). My three great passions are: books, coding, and fitness. more »

Don't miss my next post!

Sign up to get my blog posts sent directly to your inbox (plus exclusive store discounts!).

You might like these

44 comments

  1. Thank you for this Ashley! Not sure why it came up as anonymous though. I probably forgot to add my name. I’ve been looking around for a solution FOREVER and nothing seems to work. I’m gonna try this out when I have time. πŸ˜€

    Laura Plus Books recently posted: Massive Thank You
    1. Well if you’re using Tweak Me, there should already be a built-in option to show posts in more columns. πŸ™‚ That’s in Appearance > Theme Options > Blog – Archive.

  2. Hi,
    I am looking to do this for only 1 category of posts, and not for every category. Is there a way to assign this to specific category in the Category Template PHP?

    Thanks,
    Stephanie

    1. Yes you could do it for only a certain category, but it would probably involve creating a new template for your theme. Create a template for category-{category-slug}.php and put the code in there. So if your category is “Book Reviews” your template name would be category-book-reviews.php. You can read more about template hierarchies in this image.

      Then the code will only apply to that category.

  3. Thanks for this really easy to follow writeup about displaying WordPress posts in columns, it really came in handy while working on a new WordPress project for one of my clients!

    If you ever need more WordPress web development work, feel free to get in touch with me. I have created a network of great people that I trust, called the Made Better Network, that regularly refer work to. Feel free to check it out at: http://www.madebetterstudio.com/network/

    Thanks again for the great writeup, really saved my buns! πŸ™‚

  4. I’ve just use Column Shortcodes plugin but I think to try to coding your code to optimize site speed.

    Thank!!

  5. See if you can help me!

    I would like two columns until 600px width

    on 601px or more, it change for three columns.

    is it possible?

  6. Wooooo. You have helped me do my first piece of php coding! Also, it was a hugely important part to my website (the only reason I was trying to do this in the first place). Awesome instructions! It is quite a rush when you finally get it to work, now i m looking for other things to code! (not really). Is there an easy way to make it responsive so it reduces down to two and one columns as the screen gets smaller? If it is complicated then I am happy with what i’ve got. I used the more complicated method because the easy method was glitchy as predicted. So good, thank you so much.

    1. Great job Greg! πŸ™‚

      You have to use media queries to make it responsive. So, for example, instead of this:

      .half {
      	width: 50%;
      	float: left;
      }

      You might have this:

      @media (min-width: 768px) {
          .half {
      	    width: 50%;
      	    float: left;
          }
      }

      That would make it appear in two columns only if the screen size is at least 768 pixels wide.

      1. wow, another big thank you, you just saved me three days of trying and probably failing to make make that work. Nose Graze is my new favourite website!

        greg recently posted: Food Culture
  7. Great post! It’s helping a lot. I have one question how to make a white space betwin posts, the same?
    Thank You for your post, again!

  8. Maybe this is more or less a dinosaur of attempting something similar (and highlights my lack of coding expertise, lol), but in blog posts or pages where I want multiple columns, I just use the [su_row] [su_column type=”1/2″ last=”1″], etc. code. I admit that I was patting myself on the back when I was able to get my page looking the way I wanted! It’s the little things. But, it’s kind of a pain to do that every time…I had to do it about 10 times in my latest post, after all! Thanks for this post! I’m looking forward to learning a thing or two about code…it appeases the quantitative side of me πŸ™‚

    Kristi recently posted: Fresh Pasta and a Tuscan Rotolo
  9. How about if you’re using foreach. Where would you add the HTML for the column classes?

  10. I tried it in my blog but it says Parse error: syntax error, unexpected end of file in /home/behindgr/public_html/wp-content/themes/behindgraphicsV2/index.php on line 99. In the line 99 there is end of php i.e. ?>. Please help me.

  11. Just one minor Improvement ….Replace ” ” with “” … If condition is not closing and hence it is giving error on page . thanks

  12. Hi there Ashley
    I have a problem and I could not found out a free plugin that can do the next thing: to give me the ability to have recent posts … all posts from a specific category(obviously paginated like for instance 3/page not all 2000 which will be in 2000hours :)) ) on a specific page.
    I found a plugin that I could add Custom CSS to each page/post(I do not know coding at all but managed to transform few pages as a landing page eliminating the menu and the header after a long search on the net) which I think can give me this ability without messing with the theme coding(which I would probably mess up badly :)) )
    For instance the code you gave above … I have no idea how to work around it in order to put my category name in it and also my posts from that category and to be on 2 columns … and to make it work ok with my theme also :))
    The problem is that a plugin can help me out better then coding which I have zero skills beside copying what people do(worked with landing page I did).

    Thank you in advance for your guidance πŸ™‚
    Daniel

  13. Thanks for the post, Ashley. I’m trying to add related posts at the end of the content. However, the related posts display in 1 column, not 3 like expected. So I tried to use your way to divide my related posts into 3 columns. It didn’t work. πŸ™ Could you please tell me how to make it? Thanks so much.
    Below is my code:

    In the CSS
    .related-posts {
    width: 33.3%;
    float: left;
    }
    .related-posts-row {
    clear: both;
    }

    In the theme (content-singple.php)

    <div >

    ID);
    if ($categories) {
    $category_ids = array();
    foreach($categories as $individual_category) $category_ids[] = $individual_category->term_id;
    $args=array(
    ‘category__in’ => $category_ids,
    ‘post__not_in’ => array($post->ID),
    ‘posts_per_page’=> 3,
    ‘caller_get_posts’=>1
    );
    $my_query = new wp_query( $args );
    if( $my_query->have_posts() ) {
    echo ‘Related Posts’;
    while( $my_query->have_posts() ) {
    $my_query->the_post();?>
    <a href="” rel=”bookmark” title=””>

    <a href="” rel=”bookmark” title=””>

    <?
    }
    echo '’;
    }
    }
    $post = $orig_post;
    wp_reset_query(); ?>

    ” . __( ‘Pages:’, ‘skilled’ ),
    ‘after’ => ”
    ) ); ?>

  14. Hi, I used your code and it worked well for me. What if I wanted to center the posts on the page? I’ve tried align-content and align-items, but nothing has worked. I did exactly what you did in the easier code above.

  15. Using the PHP counter method, is there a way to put a vertical line in the middle?

  16. Hello,
    I have managed to make a layout of tow columns on my homepage. However, when i click to see the content of a post, i can see it only on half page instead of full page. Am i missing something?
    Thank you in advance,
    Ronin

    1. Ok, i found a solution. I created a home.php file to make the two columns layout appear only in that page. However, i’m trying to put borders around the two columns layout but the borders appear around each post. Is it possible to border all the layout as one?

  17. This post is awesome, Ashley! I found a really easy way to do this if you’re using bootstrap.

    In the containing div for your [..] stuff, you can do something like this:

    <div class="article col-sm-6″>

    This is especially helpful if you have a complicated content-loop file!

    1. Hmm, the comments stripped out my code. Not sure how to show the code in the comments, but it’s a PHP tag that calls in if(is_category()) and adds the col-sm-6 class in there.

Recent Posts

    Random Posts