Splitting the WordPress loop

by Jeffrey van Rossum

Today I needed to make a post archive page for a WordPress-theme that contained several different grids in one loop. For example, the first two posts needed to be in a 50/50-grid. The following three ones in a 33/33/33-grid and the rest in a list view. The following image will illustrate what I mean.

Likely approach

For these kind of pages, you often end up going through the loop while keeping a counter. Then, with quite a bit of if-statements, you check which partial you need to show and whether you need to open or close a grid-wrapper.

Let's take a look at an example of the code that we would end up with. And this example is probably a slimmed down version of what you would end up with in a finished template.

<?php

$count = 0;

while ( have_posts() ) {

	the_post();

	if ( $count == 0 || $count == 2 ) {
		echo '<div class="grid">';
	}

	if ( $count <= 1 ) {
		get_template_part( 'partials/post-w50' );
	} elseif ( $count > 1 && $count <= 4 ) {
		get_template_part( 'partials/post-w33' );
	} else {
		get_template_part( 'partials/post-w100' );
	}

	if ( $count == 1 || $count == 4 ) {
		echo '</div>';
	}

	$count++;
}

Alternative approach

Personally, I don't like that amount of if-statements in my templates. It quickly makes your code unreadable and complicated. So instead, I tried a different approach which I really like. In the end, it would turn the earlier code into this:

<div class="grid">
<?php
	posts_from_loop( 2, function() {
		get_template_part( 'partials/post-w50' );
	});
?>
</div>

<div class="grid">
<?php
	posts_from_loop( 3, function() {
		get_template_part( 'partials/post-w33' );
	});
?>
</div>

<?php while ( have_posts() ) { 
	the_post(); 
	?>
	<?php get_template_part( 'partials/post-w100' ); ?>
<?php } ?>

A lot more readable, and less complicated if you ask me. As you can see, the if-statements are gone. Instead, for the first two grids, I'm using a function called posts_from_loop. This is a custom function which you would need to implement in your theme. The code will be shown in a bit.

The function accepts a parameter for the amount of posts from the loop you want to go through. Additionally a callback-parameter in which you can determine which partial needs to be shown.

For the full-width posts, I fall back to the general loop-code.

The code:

<?php

function posts_from_loop( $amount, $callback ) {
	global $wp_query;
	
	$count = 0;

	while ( ( $count < $amount ) && ( $wp_query->current_post + 1 < $wp_query->post_count ) ) {
		$wp_query->the_post();

		$callback();

		$count++;
	}
}

In this code, we go through loop the specified amount of times or until there are no posts to go through anymore. With every iteration the callback-function is executed and by calling the_post function we make sure that the post data is set for our partial and we notify the global query that this post is in fact processed.

Conclusion

As mentioned earlier, I like the alternative approach since it makes the template file more tidy, less complicated and more readable. I'm curious if there other approaches to this that might be even better. If you know an alternative, feel free to share.

You can find the code at this gist.

This post was last modified 23 February 2021

Comments

Talk about this article on X.
Replied by Connieveren
Thanks for sharing
Did you like this post?

If you sign up for my newsletter, I can keep you up to date on more posts like this when they are published.