I need to wrap every 4 wordpress posts in a div

I need a div to wrap every four posts in the wordpress loop. So it would be like

<div>
four posts
</div>
<div>
four posts
</div>

my current code is this

Read More
<?php 
        $i = 0;
        $wrap_div = "<div class='frak'>";
            if ( have_posts() ) {
               echo $wrap_div;
                while ( have_posts() ) {
                    the_post();

        ?>

        <div class="wine-section">
            <?php the_post_thumbnail(); ?>
            <div class="wine-info">
                <a href="<?php the_permalink(); ?>"><?php the_title( '<h1>', '</h1>' ); ?></a>
                <?php the_meta(); ?>
            </div><!-- /wine-info -->
            <div class="c"></div>
        </div><!-- /wine-section -->

        <?php       
                if ($i % 4 == 0) { echo "</div>" . $wrap_div; }
                } // end while
            } // end if
            $i++;
        ?>

This code wraps every post individually. Any ideas?

Related posts

Leave a Reply

2 comments

  1. As geomagas pointed out – you are incrementing the variable outside of the loop. Then 0 % 4 == 0 does evaluate to true – that’s because when you divide 0 by 4, you get 0. In order to get around this situation, you need one more rule.

    Also don’t forget that with your current code if the total amount of posts is for instance 12, you will have one empty “frak” div at the end of your posts.

    <?php 
        $i = 0;
        $wrap_div = "<div class='frak'>";
            if ( have_posts() ) {
                // Grab the total posts that are being displayed
                $total_posts = $wp_query->post_count;
                echo $wrap_div;
                while ( have_posts() ) {
                    the_post(); ?>
                    <div class="wine-section">
                        <?php the_post_thumbnail(); ?>
                        <div class="wine-info">
                            <a href="<?php the_permalink(); ?>"><?php the_title( '<h1>', '</h1>' ); ?></a>
                            <?php the_meta(); ?>
                        </div><!-- /wine-info -->
                        <div class="c"></div>
                    </div><!-- /wine-section -->
                    <?php 
                    // Is this a fourth post? If so, make sure it is not the last post?
                    if ( $i % 4 == 0 && $i != 0 && ( $i + 1 ) != $total_posts ) {
                        echo '</div>' . $wrap_div;
                    }
                    $i ++;
                } // end while
                // Close the $wrap_div
                echo '</div>';
            } // end if
    ?>
    

    As you can see the if statement that prints the closing tag and the new wrap is more complex now.
    It makes sure that $i is not 0(meaning it’s still the first post) and that $i + 1 does not equal the total amount of posts displayed(for that case we close after the while() loop).

    If you’re wondering why we’re closing after the while() loop – simply because your posts might not always be exactly multiple on 4(I’m not sure about the correct translation to English here) – and if that’s case and you don’t close your div after the while loop – you’ll have troubles.

  2. You are incrementing $i outside the while loop, so inside it $i will always be ==0 and thus $i % 4 == 0.

    Move $i++; before } // end while.

    However, you should also change your condition to $i % 4 == 3, because $i % 4 == 0 evaluates to true in the very first iteration ($i=0) and will produce an initial <div> with only one post.

    Alternatively, you could keep your condition as it is, and:

    • either start with $i=1 instead of 0

    • or move $i++ right after while.

    Now, when you have an exact multiple of 4 posts, an extra, empty <div> will appear at the end. That’s because you’re assuming that, when a <div> closes, another one should automatically open. That’s not always the case.

    Assuming that you have chosen the $i % 4 == 3 solution above, and that you already have a echo '</div>'; after the while loop, change your condition to if(($i % 4 == 3)&& have_posts()).