Limit posts only on home page – ideally in functions.php

So this is a tiny bit hacky, but it achieves want you want relatively cleanly without you needing to change your themes, which was presumably the point of wanting to do it in functions.php.

First make WP_Query think it’s getting all the posts with default pagination settings as usual:

function change_posts_number_home_page( $query ) {
    if ($query->is_home() && $query->is_main_query() ) {
        $query->set( 'posts_per_page', -1 );
    }
}

add_action( 'pre_get_posts',  'change_posts_number_home_page'  );

Now add an SQL LIMIT so that WP_Query only receives 3 posts, but thinks it’s asked for all of them, and so will a) not render pagination assuming your page length is 3 or more b) will only get three posts:

function set_wpquery_limit($limits, $wpq) {
    if ($wpq->is_home() && $wpq->is_main_query() ) {
        return "LIMIT 3";
    }
}

add_filter('post_limits', 'set_wpquery_limit', 10, 2);

Notes:

  • If a better answer turns up that allows you to turn off pagination with some more clean setting, that would be the way to go as this fools with WP_Query internals so is not ideal.
  • To me doing this in the ‘presentation layer’ i.e. the theme seems clearer and cleaner, but I can see that there’s pletny of time you wouldn’t want to do that, e.g. if creating a child theme was a ton of work just to tweak this.
  • This approach tested and working and didn’t cause any problems on a clean WP with twentytwenty theme, however please test thoroughly in your situation.
  • Your original code has a } missing after the if
  • Your original code was an action hook. Actions don’t look at return values, so you don’t need a return there.