Multiple posts with one loop iteration

The question:

I want 3 post with one loop iteration, so I’m using the_post() to achieve this: (html removed)

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

    the_title();
    the_post();
    the_title();
    the_post();
    the_title();

endwhile; ?>

The problem starts, if number of posts is not divisible by 3. For example, if I have 5 posts, than this loop will still try to display 6 of them, generating empty html. How can I work it out? Or maybe I’m trying to achieve this functionality the wrong way?

@edit:
Here is HTML I wanna output to clarify my question:

<div class="row">
<div class="span3">
    <h2>Title</h2>
    <p>Content</p>
</div>
<div class="span3">
    <h2>Title</h2>
    <p>Content</p>
</div>
<div class="span3">
    <h2>Title</h2>
    <p>Content</p>
</div>
 </div>

 <div class="row">
<div class="span3">
    <h2>Title</h2>
    <p>Content</p>
</div>
<div class="span3">
    <h2>Title</h2>
    <p>Content</p>
</div>
<div class="span3">
    <h2>Title</h2>
    <p>Content</p>
</div>
</div>

So I want to surround every 3 posts with .row.

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Ultimately, this question is off-topic, because the solution has nothing to do with WordPress. Outputting posts in a grid pattern is an HTML/CSS issue, and the best-practice solutions don’t involve putting every three posts inside a separate containing <div>. Even so, you can do what you want to do, using PHP (which, technically speaking, still makes this question off-topic).

I would start by querying a number of posts divisible by 3, or else setting posts_per_page to a number divisible by 3. How you do that depends on whether you’re calling a new WP_Query() for your custom-post type loop, or if you’re filtering pre_get_posts to modify the default query. Either way, you would use the posts_per_page query argument.

Then, you can simply define a counter inside the loop, and use it to close/open DIVs as necessary:

<div class="row">
<?php
$counter = 1;
if ( have_posts() ) : while ( have_posts() ) : the_post();

    global $wp_query;
    the_title(); 
    the_content(); 
    if ( ( 0 == $counter % 3 ) && ( $counter != $wp_query->posts_per_page ) ) {
    ?>
</div><div class="row">
    <?php
    }
    $counter++;
endwhile; endif;
?>
</div>

The second part of the conditional ensures that you don’t get an empty div after the last row.

Method 2

After posting this question, I’ve had the “eureka” moment and achieved it (probably the ugly way) by surrounding my html for every post with simple if(get_the_title()). So if title doesn’t exist, than don’t display anything. But I still think there is more pretty way of doing this.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment