Simple, free resources to help you build a better WordPress website.

Sign up for our newsletter.

How to Build a Custom Page Template for Blog Posts

When building out a custom “Blog” section for your WordPress site, sometimes it’s easiest to create a custom page template that you can customize that allows you to set the page location (such as https://upthemes.com/blog), as well as your very own title and description that are displayed at the top of the blog section.

Step 1. Copy index.php to tpl_blog.php

To start, copy your index.php file from your current theme and rename the copied file tpl_blog.php. The reason for this is to get an exact copy of the theme functions and HTML structure from your current theme and to create a page template that will eventually be selectable from the ‘Page Template’ dropdown.

Step 2. Create Page Template ID

In your new file tpl_blog.php, you need to add a special comment to the top of the file that WordPress will recognize as a custom template.


/*
Template Name: Blog Posts
*/

Simply add that to the very top of your page and now WordPress will recognize it in the Edit Page screen sidebar.

3. Use Custom Query for Posts

Place this below the get_header() template tag:

<?php query_posts('post_type=post&post_status=publish&posts_per_page=10&paged='. get_query_var('paged')); ?>

This will override the current page query with a custom query for 10 paginated blog posts. Since we’re using query_posts(), we don’t need to generate a new custom WP_Query to store the custom query.

4. Add Navigational Links for Pagination

Below your post loop, add some links for pagination like so:

<div class="navigation">
	<span class="newer"><?php previous_posts_link(__('« Newer','example')) ?></span> <span class="older"><?php next_posts_link(__('Older »','example')) ?></span>
</div><!-- /.navigation -->

This should be between the endwhile; and endif; sections of code in your theme.

5. Reset the Query

Once you’ve output all your posts and navigation, you can use wp_reset_query() to reset the query_posts() results that you created earlier. In lamens terms, you’ve now reset the query to what it was before you called query_posts().

6. Putting it all together

Here’s a completed page template that utilizes everything described above with additional markup and includes the loop:

<?php get_header(); ?>

	<div id="content">

        <?php query_posts('post_type=post&post_status=publish&posts_per_page=10&paged='. get_query_var('paged')); ?>

	<?php if( have_posts() ): ?>

        <?php while( have_posts() ): the_post(); ?>

	    <div id="post-<?php get_the_ID(); ?>" <?php post_class(); ?>>

        	<a href="<?php the_permalink(); ?>"><?php the_post_thumbnail( array(200,220) ); ?></a>

                <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>

                <span class="meta"><?php author_profile_avatar_link(48); ?> <strong><?php the_time('F jS, Y'); ?></strong> / <strong><?php the_author_link(); ?></strong> / <span class="comments"><?php comments_popup_link(__('0 comments','example'),__('1 comment','example'),__('% comments','example')); ?></span></span>

		<?php the_excerpt(__('Continue reading »','example')); ?>

            </div><!-- /#post-<?php get_the_ID(); ?> -->

        <?php endwhile; ?>

		<div class="navigation">
			<span class="newer"><?php previous_posts_link(__('« Newer','example')) ?></span> <span class="older"><?php next_posts_link(__('Older »','example')) ?></span>
		</div><!-- /.navigation -->

	<?php else: ?>

		<div id="post-404" class="noposts">

		    <p><?php _e('None found.','example'); ?></p>

	    </div><!-- /#post-404 -->

	<?php endif; wp_reset_query(); ?>

	</div><!-- /#content -->

<?php get_footer(); ?>

24 Comments

  1. Avatar
    Ash says:

    Thanks for a great post. I have a problem where “Older” points to blog/page/2 but when you click it, the site stays on blog/ . Any ideas?

  2. Avatar
    Melodie says:

    Hey!

    Thank-you! I’ve been customizing a wordpress website and I detest the blog page layout. I wasn’t sure how to make a template but this tutorial gave me some confidence that it’s possible. It worked but it needs to be edited to look a bit nicer. All the content shows up. It’s a good start though and I appreciate the tutorial.

    THANK YOU

    • Avatar
      Rishi says:

      Why don’t you remove author_profile_avatar_link(48); on line no 17, since it isn’t by default on all WordPress theme. I tried your code on my TwentyTweleve theme, it worked greatly but I’ve to remove the above mentioned code.

  3. Avatar
    fabien says:

    Hello,

    I did the same steps that you showed. And i changed the template of the page to the template i created, but it’s still showing the posts like the previous template.

    Please advise.

    Thank you

  4. Avatar
    Enrique says:

    This is great. Thanks! Can we do something similar with a portfolio items?
    what would the query for the portafolio items be?

  5. Avatar
    Kelli says:

    I’m so sorry to bother you so long after you posted this!

    Worked like a dream for me. So happy! Only question – they are scrolling on the page brilliantly, but clicking the title or post doesn’t go into the individual posts (ie, to leave comments, etc). How can I do that OR get the ability for users to leave comments as they can in the single blog post pages? I’m sure I’m just missing something.

  6. Avatar
    Rushax says:

    Sorry to be really over the top but the first line is missing the ‘?’
    Just thought it might be worth mentioning in case people come just to copy & paste.
    Great read, thanks very much for the tutorial!

Leave a Reply

Your email address will not be published. Required fields are marked *