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
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.
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. π
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.
Working on a secret project. π
Ah π New projects are so exciting!
Wow, I’m absolutely flattered that this question was asked Laura and Ashley (didn’t notice it til now lol). I can see more of these styled blogs coming about which makes me happy ^_^
Hah, great post! Luckily I don’t need it because I have this awesome theme that does all that for me. I just have to click on the button! I don’t know if you’ve heard of it? It’s called the Tweak Me theme. π It’s totally amazing!
Aw shucks ♥
I’m glad Laura asked this. And thank you so much, Ashley, for answering! π I tried implementing columns on my homepage but no mattered which tutorials I followed, I couldn’t get it done. I’ll definitely try your method some time.
Good luck!! π
Ooh, thanks for this, Ashley! I don’t usually like blogs with multiple columns of posts because they can look so messy sometimes, but if done correctly, they can look pretty good. Looks complicated, but I’ll be sure to give this tutorial a try if I ever want to switch to 2 or 3 columns! π
Thanks for this tutorial! I’d been wanting to do this for a while, but hadn’t wanted to take the time to work out the php code myself. Big time saver… and very easy to cut and paste π
Exactly what I needed! Thank you!
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
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.
How to do it in twentyfifteen ?
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! π
I’ve just use Column Shortcodes plugin but I think to try to coding your code to optimize site speed.
Thank!!
Thank very soo thankyou much!!! XD
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?
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.
Great job Greg! π
You have to use media queries to make it responsive. So, for example, instead of this:
You might have this:
That would make it appear in two columns only if the screen size is at least 768 pixels wide.
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!
Thanks π
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!
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 π
Thank you very much, Ashley
How about if you’re using foreach. Where would you add the HTML for the column classes?
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.
Best Solution I Got , Love you … I was looking for a simple solution from a week
Just one minor Improvement ….Replace ” ” with “” … If condition is not closing and hence it is giving error on page . thanks
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
Thanks a lot for this!
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’ => ”
) ); ?>
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.
nice work it helped me
Using the PHP counter method, is there a way to put a vertical line in the middle?
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
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?
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!
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.
Wow. Thank you!
Very helpful article and help me a lot.
Thanks