Typominima, free typography based minimal WordPress theme

WordPress How To: Latest Posts by Category Archive

WordPress - Latest posts by categoryOne technique that is most common with WordPress magazine or news style themes is the display of an archive of the latest posts by category, as simple titles or with post excerpts. This is useful for the previously mentioned theme styles, but not only. It can be used to set up custom blog homepages, 404 pages, landing pages or even a special archive page.

This tutorial will help you build a ‘Latest Posts by Category Archive‘ in a very easy way. The widths in the CSS styling presented below have been calculated based on the default WordPress theme, assuming that is the most common theme available to anyone.

If you are looking for a plugin to generate such an archive, please check out: WP Plugin: Latest Posts by Category Archive.

Setting up the page template

Open up you favorite code editor and create a blank document. Save the document as ‘category-archive.php’ (or any other name you’d prefer) in the default WordPress theme directory (wp-content/themes/default).

The first step is to asign our new template a name and a page-like structure, so based on the default theme’s page template, the code you should paste in your new document is:

<?php
/*
Template Name: Category Archive
*/
?>

<?php get_header(); ?>

<div id="content" class="narrowcolumn">

	<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
	<div class="post" id="post-<?php the_ID(); ?>">
	<h2><?php the_title(); ?></h2>
		<div class="entry">
			<?php the_content('<p class="serif">Read the rest of this page &raquo;</p>'); ?>

			<?php wp_link_pages(array('before' => '<p><strong>Pages:</strong> ', 'after' => '</p>', 'next_or_number' => 'number')); ?>

		</div>
	</div>
	<?php endwhile; endif; ?>

	<!-- Category Archive Start -->
	<!-- Category Archive End -->

</div>

<?php get_sidebar(); ?>

<?php get_footer(); ?>

The template above will make sure to display the page name you set up, and also, any additional content you might want to add before the archive, from you WordPress page editor. We will be adding our ‘latest posts by category’ code between the ‘Category Archive Start’ and ‘Category Archive End’ comments.

Adding the archive’s PHP code

Simply put, the code below will cycle through the first-level categories of your blog (parent categories), check for the ones that are not empty and if this condition is met, return an unordered list of the latest 5 post from each category. Empty categories will not be displayed.

<?php
/*
Template Name: Category Archive
*/
?>

<?php get_header(); ?>

<div id="content" class="narrowcolumn">

	<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
	<div class="post" id="post-<?php the_ID(); ?>">
	<h2><?php the_title(); ?></h2>
		<div class="entry">
			<?php the_content('<p class="serif">Read the rest of this page &raquo;</p>'); ?>

			<?php wp_link_pages(array('before' => '<p><strong>Pages:</strong> ', 'after' => '</p>', 'next_or_number' => 'number')); ?>

		</div>
	</div>
	<?php endwhile; endif; ?>

	<!-- Category Archive Start -->
	<ul class="catArchive">
	<?php
	$catQuery = $wpdb->get_results("SELECT * FROM $wpdb->terms AS wterms INNER JOIN $wpdb->term_taxonomy AS wtaxonomy ON ( wterms.term_id = wtaxonomy.term_id ) WHERE wtaxonomy.taxonomy = 'category' AND wtaxonomy.parent = 0 AND wtaxonomy.count > 0");

	$catCounter = 0;

	foreach ($catQuery as $category) {
			
		$catCounter++;

		$catStyle = '';
		if (is_int($catCounter / 2)) $catStyle = ' class="catAlt"';

		$catLink = get_category_link($category->term_id);

		echo '<li'.$catStyle.'><h3><a href="'.$catLink.'" title="'.$category->name.'">'.$category->name.'</a></h3>';
			echo '<ul>';

			query_posts('cat='.$category->term_id.'&showposts=5');?>

			<?php while (have_posts()) : the_post(); ?>
				<li><a href="<?php the_permalink() ?>" rel="bookmark" title="<?php the_title(); ?>"><?php the_title(); ?></a></li>
			<?php endwhile; ?>

				<li><a href="<?php echo $catLink; ?>" title="<?php echo $category->name; ?>">More <strong><?php echo $category->name; ?></strong></a></li>
			</ul>
		</li>
		<?php }	?>
	</ul>
	<!-- Category Archive End -->

</div>

<?php get_sidebar(); ?>

<?php get_footer(); ?>

You should now save your file, because we’re done editing it. As you can see, the archive code has been added between the ‘Start’ and ‘End’ comments. Now let’s go through the code and dissect it.

The PHP code explained

The first thing we do is to set up a database query to cycle through the non-empty parent categories:

$catQuery = $wpdb->get_results("SELECT * FROM $wpdb->terms AS wterms INNER JOIN $wpdb->term_taxonomy AS wtaxonomy ON ( wterms.term_id = wtaxonomy.term_id ) WHERE wtaxonomy.taxonomy = 'category' AND wtaxonomy.parent = 0 AND wtaxonomy.count > 0");

You can further tweak this query to exclude categories or specify categories to be listed based on their ID, with the use of the MySQL comparison functions NOT IN or IN.

Let’s say that you’d like the archive to exclude the categories with IDs 2, 5 and 6. Your query would become:

$catQuery = $wpdb->get_results("SELECT * FROM $wpdb->terms AS wterms INNER JOIN $wpdb->term_taxonomy AS wtaxonomy ON ( wterms.term_id = wtaxonomy.term_id ) WHERE wtaxonomy.taxonomy = 'category' AND wtaxonomy.parent = 0 AND wtaxonomy.count > 0 AND wterms.term_id NOT IN (2,5,6)");

Similarly, if you want to display only the categories with IDs 2,5 and 6, you’d have:

$catQuery = $wpdb->get_results("SELECT * FROM $wpdb->terms AS wterms INNER JOIN $wpdb->term_taxonomy AS wtaxonomy ON ( wterms.term_id = wtaxonomy.term_id ) WHERE wtaxonomy.taxonomy = 'category' AND wtaxonomy.parent = 0 AND wtaxonomy.count > 0 AND wterms.term_id IN (2,5,6)");

For further help with comparison operators and functions, you can check out the MySQL manual.

Next, we set up a category counter which will be incremented each time a category will be displayed. Based on this counter, the code adds a ‘catAlt‘ class that you can use to style differently consecutive categories. In our case, we’ll use it to shift the categories into two columns. This is were the alternate classes are assigned:

$catCounter++;

$catStyle = '';
if (is_int($catCounter / 2)) $catStyle = ' class="catAlt"';

The category list is built by the use of foreach and it helps retrieve vital information about the categories, such as name and permalink:

foreach ($catQuery as $category) {
	/* Code used to retrieve and display the latest posts */
}

After we display the category title and link through this line of code

echo '<li'.$catStyle.'><h3><a href="'.get_category_link($category->term_id).'" title="'.$category->name.'">'.$category->name.'</a></h3>';

we continue by using a custom query to retrieve the latest 5 posts from the current category in the cycle, followed by a link to the complete category archive:

query_posts('cat='.$category->term_id.'&showposts=5');?>

<?php while (have_posts()) : the_post(); ?>
	<li><a href="<?php the_permalink() ?>" rel="bookmark" title="<?php the_title(); ?>"><?php the_title(); ?></a></li>
<?php endwhile; ?>
	<li><a href="<?php echo $catLink; ?>" title="<?php echo $category->name; ?>">More <strong><?php echo $category->name; ?></strong></a></li>

And that’s about everything in terms of coding! Now, onto the CSS styling.

Styling the archive

Find the style.css file in your default theme’s directory, open it and scroll down to the end of the file. Now copy the code below and paste it in your file.

/* Latest posts by category styles */

.catArchive {
	width: 450px;
	overflow: hidden;
	margin: 20px 0 0 0;
	padding: 0;
	list-style-type: none;
}

.catArchive h3 {
	font: normal bold 18px sans-serif;
	border-bottom: 1px solid #666;
	margin: 0;
	padding: 0 0 3px 0;
	display: block;
}

.catArchive li {
	display: block;
	float: left;
	width: 210px;
	margin: 0 30px 30px 0;
}

.catArchive ul {
	margin: 0;
	padding: 0;	
}

.catArchive li li {
	border-bottom: 1px solid #ddd;
	margin: 0;
	padding: 4px 0;
}

.catAlt {
	margin-right: 0 !important;
}

Now, save the file. We’re done!

Note: Keep in mind that column sizes have been calculated based on the available space (450 pixels) in the default theme’s content area. So, our columns should each be 210 pixels wide, with a 30 pixels spacing between them.

Since the column shifting is done with the help of float, I’ve set the overflow to hidden to stretch the list full height. This can only work with a fixed given container width, which in our case is 450px set on .catArchive.

If your new to “floating”, Sarah has posted a fairly easy to understand article about the float property on BloggingTips.com.

You can download an archive containing both source files: Download.

More Blogsessive Content

ThemeForest

This article has 45 comments

  • Great work, Alex.

    But perhaps you need a syntax highlighting plugin. The code is unreadable unless I copy and paste in my text editor.

  • Wops.. Seems like I type too fast before it was loaded. LOL… you do have that plugin. ;)

  • Hendry, I am using a syntax highlighting plugin and I can see it in use withing this article. Maybe you should hit the refresh and wait a second until the plugin goes through the code and re-displays the formatted code. Anyways, glad you enjoyed the tutorial.

  • This post is really awesome, will help me learn more and make my own themes :)

  • Pretty smart, Alex. I use kind of the same trick! :)

  • Although a plugin could provide some nice configuration features, writing a function for this seems also a good idea.

  • Thank you all for your comments and I’m glad that you’ve found this useful.

    Update: Plugin is ready. Get it!

    Seeing that people suggested that this should be transformed into a plugin I’ve decided to do so and currently working on it.

    The plugin will be based mainly on the code in this tutorial, but with a few changes required to make this work either within the loop or outside of it, without interfering with the queried page/post’s variables. Also, possibility to display post excerpts will be added.

  • Hey Alex…great work and research I must say. Here, I would like to share my issue with you all. I recently got my Graphic Design Blog (http://www.graphicdesignblog.org)redesigned using a wordpress theme. I am recieving mixed reactions and suggestionsfrom my readers.

    Your detailed work and exciting blog indicates, you can help me improve my design. Please do chk it…thanks!

  • Thanks for the code tip!

    This was exactly what I needed for the Multi-level Navigation Plugin.

  • Alex, I would really love to see a RSS feed button for each category!

  • useful post ! thank you. I’ll try

  • How display all categories – both empty and not empty ?

  • d4b, look for this in the category query:

    ” AND wtaxonomy.count > 0″

    And remove it.
    Even though it wouldn’t make sense displaying a “archive of nothing”.

  • Jamiel Sharief

    Fantastic, thanks for this tutorial.

  • Can this be used to display an index of articles sorted by title? If so, what needs to be edited? Thanks.

  • Jack, that can be achieved by modifying the “query_posts()” line and assigning a new order for the posts retrieved.

    You can read more about this and the query_posts template tag on the WordPress Codex: http://codex.wordpress.org/Tem.....uery_posts

  • excellent article, very useful. any ideas on how to make a widget display more than 15 latest posts?

  • Is there a way to sort the categories in orders of ascending, e.g. cat 6, 7, 8, 9 instead of 9, 8, 7, 6 as what I am currently experiencing?

  • Help

    I put the code into the Sidebar but now when I open any page it directs to a post page for one of my categories…

    does anyone know what I am doing wrong?

  • Is there any way to just return the category name and post name but not the post.

  • Hunter, this code sample does not return any post content or excerpt. Are you sure you did it right?

  • I got it. Thanks for the help!

  • nice tricks… but my site was image based site… maybe.. i modified above code to import custom field value per post to show image for selected category….

  • Firstly enter your blog, found this cool article… tq for such great info…

    Your code above work perfectly… BUT…

    How if i want show.. category archive for all subcategory or child category per parent category

    Example:
    My site have 3 parent category with huge number child category each.

    I want to make 3 separate archive page for each parent category which show. the latest post of each child category..

    I need your help and wait for this… may be other need too this tricks..

    TQ in Advance… thumbs up..

  • I have one problem with my screep i have add codet but i see i have one erro
    At my display .

    Please open image and you see whe i have error….
    http://img4.imageshack.us/img4.....t004nt.jpg

    I wite for questios

    Thanks for all.

  • Just a quick thank you. This solution was very, very helpful. I had been pulling my hair out trying to organize my Archives page (at http://williamlanday.com/blog/archives/ ) when I finally found this. Great job.

  • @ Melvin

    You wrote:
    Is there a way to sort the categories in orders of ascending, e.g. cat 6, 7, 8, 9 instead of 9, 8, 7, 6 as what I am currently experiencing?

    I think this should do the trick,
    add some code in the database query:

    $catQuery = $wpdb->get_results(
    “SELECT * FROM $wpdb->terms AS wterms INNER JOIN $wpdb->term_taxonomy AS wtaxonomy ON
    ( wterms.term_id = wtaxonomy.term_id ) WHERE wtaxonomy.taxonomy = ‘category’ AND wtaxonomy.parent = 0
    AND wtaxonomy.count >= 0 AND wterms.term_id NOT IN (38,1) ORDER BY wterms.term_ID DESC”);

    And here is a way to sort by catgeory name instead of catgeory ID:

    $catQuery = $wpdb->get_results(
    “SELECT * FROM $wpdb->terms AS wterms INNER JOIN $wpdb->term_taxonomy AS wtaxonomy ON
    ( wterms.term_id = wtaxonomy.term_id ) WHERE wtaxonomy.taxonomy = ‘category’ AND wtaxonomy.parent = 0
    AND wtaxonomy.count >= 0 AND wterms.term_id NOT IN (38,1) ORDER BY wterms.name ASC”);

  • Is there a way to get posts older than the current visited article? For example, is the current article id 100, I want 5 posts of the same category with an id lower than 100. I haven’t find a solution for this, maybe someone has a hint for me.

  • I love you. I’ve been fervently trying to figure out how to accomplish this for months. Doesn’t help I’m already mired down in a really complicated loop, but this trick really eases a lot of the pain I’m going to have to go to. You got a donate link around here somewheres?

  • Me again,

    Just thought I’d mention that the declaration overflow: hidden; breaks Safari 4. I took it out and it still displays fine in Firefox, as well as Safari 4.

  • Thanks!! Helped me a ton!!

  • This is great stuff thanks. However, I’m using this in WordPress 3 and would like to use it with a custom post type and custom taxonomy in place of the blog and category. Any hints would be most appreciated!

  • Is there a way to specific a custom sort order for the categories (i.e. not by name, nor by ID)?

    I’m using the ‘Category Order’ plugin (http://wordpress.org/extend/pl.....ategories/) which let’s me customize the order of how categories are listed, is there a way to order the categories the same order that I specify in the Category Order plugin?

    Thanks in advance.

  • Hi all,
    i’m building my own wordpress theme and i’d like to show some random posts by 12 little pics in the homepage.
    This is the code i tried to do and it works fine. The problem is that i wanto to EXCLUDE a specific category. How can i modify the code?
    Can anyone help me?

    Thanks in advance.

    Max

    This is the code i used:

    get_results(“SELECT ID FROM $wpdb->posts WHERE post_status = ‘publish’ AND post_type = ‘post’ ORDER BY RAND() LIMIT 12″);

    foreach ($randompost as $post) {
    $ID = $post->ID;
    $postid = get_post($post->ID);
    $title = $postid->post_title;
    $values = $wpdb->get_var(“SELECT meta_value FROM $wpdb->postmeta WHERE post_id = $ID AND meta_key = ‘Image’ “);
    ?>

    <a href="” rel=”bookmark” title=”"><img src="/scripts/timthumb.php?src=/&w=&h=&zc=1&q=100″
    alt=”" class=”left” width=”px” height=”px” />

    ID;
    $the_content =$wpdb->get_var(“SELECT post_content FROM $wpdb->posts WHERE ID = $id”);
    $home = get_option(‘home’);
    $pattern = ‘!

    <a href="” rel=”bookmark” title=”">
    <img src="/scripts/timthumb.php?src=&w=&h=&zc=1&q=100″
    alt=”" class=”left” width=”px” height=”px” />

  • Thank you! That was exactly what I was looking for. And the css was icing on the cake!

  • Has anyone figured out how to use this along with custom post types for WP 3+ ??

    Any ideas would be awesome!

    Thanks -
    Dan

  • This is the most valuable WP tutorial I found today.

    This gives me a lot of new ideas in exploring WP.

    Thanks.

  • Great wordpress hack to see here

  • shamil

    its not workin in IE.
    :S
    any suggestions Alex ?

  • shamil, this is not a “browser specific” piece of code. Most of the code is PHP, and DB queries. There is not cross-browser issue here. If you’re experiencing any problems with IE display, that might just come from your theme’s design and CSS styling. Just in case, you could simply play with the floats and overflow in the CSS of the tutorial, but I doubt that would be the issue.

  • Thank you so much for this tutorial! This is the only good post I found showing how to do this without a plugin.

    By the way, &showposts has been depreciated. It was replaced by &posts_per_page. Simply swapping those two items out should help bring the code up-to-date.

    It’s also worth noting that it’s possible to show an unlimited number of posts under each category by setting &posts_per_page=-1.

  • Hi, thanks for this article…

    I have a question…I want to create the custom post type archive page (for example: news) with the same structure, all news subdivide by categories (by custom taxonomies). How can I do?

    Thanks for all replies!

  • Thanks For Tutorial..

Add a comment

Submit comment!

Let's play nice! Comments are all about conversation. How am I supposed to address you if you use keywords as your name?
Not to mention that you risk having your comment spammed or deleted.
I would really appreciate it if you use your name or pseudonym.

11 blog posts linking to this article

  1. WordPress How To: Latest Posts by Category Archive
  2. Weekend Links - Feb 14, 2009 | OMNINOGGIN
  3. links for 2009-02-15 | This Inspires Me
  4. Howto: Displaying Recent Posts per Category — WPCandy — WordPress Themes, Plugins, Tips, and Tricks
  5. WordPress CMS 技巧:按照分类调用最新文章 at 站趣-分享建站的乐趣
  6. WP Plugin: Latest Posts by Category Archive | Blogging Tips from Blogsessive
  7. Interesting Articles #17 » DivitoDesign
  8. 10 WordPress ‘HOW-TO’ to Give Your Blog the Quality it Deserves
  9. [WordPress] カテゴリーアーカイブページテンプレート - ハウスウエディング [665-667]
  10. 10 WordPress ‘HOW-TO’ to Give Your Blog the Quality it Deserves | web3mantra
  11. 10 Tips to Make Your WordPress Blog Outstanding - JustAnART