How to display different number of Posts in different views in WordPress

Posted on

In Genesis Facebook group a user wants to know how

  • 18 posts can be shown on search and category archives
  • 6 posts can be shown on the first page of Posts page

with the default number of posts as set in Settings > Reading appearing in all other views incl. the paginated pages of the Posts page.

We can set this up using pre_get_posts filter.

Add the following in child theme’s functions.php:

add_action( 'pre_get_posts', 'sk_query_offset', 1 );
/**
 * Change Posts Per Page in various views
 *
 * @author Sridhar Katakam
 * @link https://sridharkatakam.com/display-different-number-posts-different-views-wordpress/
 * @param object $query data
 *
 */
function sk_query_offset( &$query ) {

	// if this is not the main query or on the admin back end, abort.
	if ( !$query->is_main_query() || is_admin() ) {
		return;
	}
	// if search or category archive, set 18 posts per page
	elseif ( is_search() || is_category() ) {
		$query->set( 'posts_per_page', '18' );
	}

	// if not Posts page, abort. i.e., rest of the code below applies to Posts page.
	if ( !$query->is_home() ) {
		return;
	}

	// First, define your desired offset...
	$offset = -4; // 10 - 4 = 6 where 10 is the number set at Settings > Reading

	// Next, determine how many posts per page you want (we'll use WordPress's settings)
	$ppp = get_option( 'posts_per_page' );

	// Next, detect and handle pagination...
	if ( $query->is_paged ) {

		// Manually determine page query offset (offset + current page (minus one) x posts per page)
		$page_offset = $offset + ( ( $query->query_vars['paged']-1 ) * $ppp );

		// Apply adjust page offset
		$query->set( 'offset', $page_offset );

	}
	else {

		// This is the first page. Set a different number for posts per page
		$query->set( 'posts_per_page', $offset + $ppp );

	}
}

add_filter( 'found_posts', 'sk_adjust_offset_pagination', 1, 2 );
function sk_adjust_offset_pagination( $found_posts, $query ) {

	// Define our offset again...
	$offset = -4;

	// Ensure we're modifying the right query object...
	if ( $query->is_home() && is_main_query() ) {
		// Reduce WordPress's found_posts count by the offset...
		return $found_posts - $offset;
	}
	return $found_posts;
}