DiggingIntoWordPress

by Chris Coyier & Jeff Starr

Display Blog Posts on any Page (with navigation)

Posted by on

By default, your latest WordPress posts are displayed on the home page, with older posts available via post navigation on /page/2/, /page/3/, and so on. In this DigWP post, we’ll explain how to display your blog posts on any static page using a custom WP_Query loop that works beautifully with post navigation.

For example, if you’re displaying a static page for your front page (as specified in the Reading Settings), you may want to display your blog posts separately, perhaps on a custom “blog” page. That’s what I ended up doing for the xy.css blog while using a static (post-less) home page. It’s nice because post-navigation works intuitively, like so:

  • http://xycss.com/blog/ — displays latest blog posts
  • http://xycss.com/blog/page/2/ — displays second page of posts
  • http://xycss.com/blog/page/3/ — displays third page of posts
  • ..etc..

As you can imagine, this is super-useful when setting up custom CMS configurations, for example when using the home page as a forum, storefront, or landing page. For such scenarios, here’s how to display blog posts on a custom page (with navigation!).

Update! almost immediately after this article posted, Brian Krogsgard explains an even easier way: create two pages and then set one as the “front page” and the other as the “posts page” via Reading Settings. The method here may be useful for further customization (via query parameters), but using the settings-only method is a better way to do it.

Step 1: Page template

Create a blank page template named “page-blog.php” and include the following code:

<?php 
/*
	Template Name: Blog
*/
?>
<?php get_header(); ?>

	<article>

		<?php // Display blog posts on any page @ http://m0n.co/l
		$temp = $wp_query; $wp_query= null;
		$wp_query = new WP_Query(); $wp_query->query('showposts=5' . '&paged='.$paged);
		while ($wp_query->have_posts()) : $wp_query->the_post(); ?>

		<h2><a href="<?php the_permalink(); ?>" title="Read more"><?php the_title(); ?></a></h2>
		<?php the_excerpt(); ?>

		<?php endwhile; ?>

		<?php if ($paged > 1) { ?>

		<nav id="nav-posts">
			<div class="prev"><?php next_posts_link('&laquo; Previous Posts'); ?></div>
			<div class="next"><?php previous_posts_link('Newer Posts &raquo;'); ?></div>
		</nav>

		<?php } else { ?>

		<nav id="nav-posts">
			<div class="prev"><?php next_posts_link('&laquo; Previous Posts'); ?></div>
		</nav>

		<?php } ?>

		<?php wp_reset_postdata(); ?>

	</article>

<?php get_footer(); ?>

That’s the money shot, just plug it in and take charge with your own parameters for WP_Query and you’re all set. For example, instead of showing 5 posts, you can set showposts=10 or whatever works best.

Note that the post-navigation is conditional, such that the first page of posts (i.e., your /blog/ page) doesn’t display empty markup/styles for the “next posts” link. Learn more about optimizing WordPress post navigation.

Note also that the HTML used in this example is rudimentary to keep things simple. You’ll probably need to make a few changes to the markup to synchronize with your theme design.

Step 2: Add New Page

Once page-blog.php is complete and uploaded to the server, log in to the WP Admin and visit the Add New Page screen. There, create a new page named “Blog” (or whatever you want), and set its Template as “Blog” from the “Page Attributes” panel.

Done! Now visit the Blog page after publishing and you should see the custom WP_Query loop working its magic: your latest blog posts will be displayed on the page along with navigation to previous posts, if they exist ;)

Wrap-up

WordPress makes it easy to display your blog posts just about anywhere. In this post, we explain how to display posts on any page using a custom WP_Query loop that supports post navigation, which can be super-useful when configuring WordPress as a customized CMS.

16 Responses

  1. Brian Krogsgard January 12, 2013

    What you should do is just change the option in your reading section. Create two pages for home and blog, then set them as the static home page and posts page in Settings -> Reading.

    Using WP_Query in a template for your blog is pointless in your scenario, unless you aren’t sharing parts that would make your method necessary.

    • I should have known there was an easier way! So for the posts page, WP will automatically display posts on the selected page instead of the page content?

      • Brian Krogsgard January 12, 2013

        If you set that page as the posts page in the reading settings, then yes. And then your template hierarchy will be so that whatever is in home.php (or down the hierarchy if you don’t have home.php) will show up on the blog page. No templates or additional code required.

        • Yes, that’s a much better way to do it, thanks for explaining. I’ve updated the post with a note about this, hopefully the template method will be useful for more advanced customization.

  2. It’s better to add this code

    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

    above $wp_query
    and showposts is deprecated.
    It’s better to use posts_per_page

  3. The method here may be useful for further customization (via query parameters)…

    Even then, this method over-complicates. If you need to modify the query parameters for the main query on the blog posts index, just filter $wp_query via pre_get_posts. For example, if you only want to display 5 posts per page:

    function digwp_filter_pre_get_posts( $query ) {
     if ( is_home() && $query->is_main_query() ) {
      $query->set( 'posts_per_page', '5' );
     }
    }
    add_action( 'pre_get_posts', 'digwp_filter_pre_get_posts' );

    And you’re done.

    • That’s very useful, thank you Chip!

    • Personally, I prefer this way over rewriting a custom WP_Query object, and then reverting back to the main query. It’s a hassle-free and friendly solution.

      Also, you can easily put this snippet in a functionality plugin and not have to worry about what theme is being used. That way, it should work on any theme.

  4. I think that you need restore the old wp_query with $wp_query = $temp after $wp_reset_query. You need this if you want, for example, display the content of blog after display the posts.

  5. When I need a custom template for the front page and a blog section, I create a front-page.php file and eventually a home.php, if the blog template needs customizing. Then I create both pages which won’t have any actual content in the WYSIWYG and set them in the reading settings.

  6. Of course, remember you shouldn’t use the <article> tag if you’re in a theme built on XHTML 1.0, which is really most of them at this stage.

  7. Jeff

    when you’re creating your own WP_Query object, you should use wp_reset_postdata() instead of wp_reset_query()
    and, acutally you’ve explained this in anoher post:
    http://digwp.com/2011/09/3-ways-to-reset-the-wordpress-loop/

  8. Hi, if I were you I’d replace “showpost=5″ with “array(‘posts_per_page’ => 5)” because showpost is deprecated.

  9. Thanks i have been searching for this kind of functionality from past four days, I have to implement this on one of the client site..

    Thank you very much for the post…
    It’s very helpful for me…

  10. Hi Jeff great tut and comments from everyone… I’ll have to try this out my site.

Comments are closed. Contact us with any critical information. Thank you!

Code is poetry