WordPress

WordPress Theme Tutorial: MSNBC-like Home Page Category Listing

By default, the home page of a WordPress blog will show a list of most recent blog posts. That is simply the usual behavior of a blog. But then, if you’d like to use WordPress as a content management system, then you might want things to show a little differently. This is especially true when creating a magazine style WordPress theme.

Take a look at MSNBC.com. There, if you scroll down a little bit, you will be able to see a list of category blocks (”U.S., World and Politics”, “Business”, “Sports”, and so on). Within each block you can see one most recent post with excerpt, then a list of seven previous posts.

Image example of MSNBC category listing

This article will discuss a way to do that with WordPress.

The General Idea

This is what we want to achieve:

  1. Create good HTML markup for the listing.
  2. Grab all available categories.
  3. For each category, grab some of its most latest posts.
  4. For the first post, display its title and excerpt.
  5. For the rest of the posts, only display the titles and put them inside an unordered list.
  6. Apply CSS to display everything in an interesting way.

Not too complicated, eh?

Also, please note that since this is to be displayed on the front page, then the following codes should be placed inside index.php.

1. Create good HTML markup for the listing.

Let’s use something like this:

<ul id="cat-listing">
  <li class="cat-block">
    <h3>Category Name</h3>
    <div class="cat-most-recent">
      <h4><a href="#">This is post #1</a></h4>
      <div class="cat-list-excerpt">
        This is the excerpt for post #1. You could expect a few sentences here. Like this one.
      </div>
    </div>
    <ul class="cat-recent-list">
      <li><a href="#">This is post #2</a></li>
      <li><a href="#">This is post #3</a></li>
      <li><a href="#">This is post #4</a></li>
      <li><a href="#">This is post #5</a></li>
      <li><a href="#">This is post #6</a></li>
      <li><a href="#">This is post #7</a></li>
    </ul>
  </li>

  <li class="cat-block">
   ...etc
  </li>
</ul>

2. Grabbing all available categories

$categories = get_categories();

This is the most simple code that can be used. There are a few parameters you can use for the get_categories() function, but for our example using the default (leaving the parameter empty) is fine.

3. For each category, grab some of its most latest posts.

<ul id="cat-listing">
<?php
  $categories = get_categories();
  foreach ($categories as $cat) {?>
  <li class="cat-block">
  <h3><?echo $cat->name; ?></h3>
<?php
  $catID = $cat->$cat_ID;
  query_posts("showposts=3&cat=$catID");
?>
  </li>
<?php } //end foreach ?>
</ul>

The basic idea is that, after getting the list of categories, we put it inside a foreach where we will construct the cat-block list item. Inside that list item we do the query_post for the category ID.

4. For the first post, display its title and excerpt.

Next, we zoom in and start working inside the foreach.

  foreach ($categories as $cat) { ?>
  <li class="cat-block">
    <h3><?echo $cat->name; ?></h3>
    <?php
    $catID = $cat->cat_ID;
    query_posts("showposts=8&cat=$catID");
    $first=1;
    while (have_posts()) : the_post();
      // Latest post with excerpt
      if($first) {
    ?>
    <div class="cat-most-recent">
      <h4><a href="<?php the_permalink() ?>" rel="bookmark" class="title"><?php the_title(); ?></a></h4>
      <div class="cat-list-excerpt">
        <?php the_excerpt(); ?>
      </div>
    </div>
    <?php
      } // end if
    ?>
    <?php endwhile; ?>
    </ul>
  </li>
  <?php } //end foreach ?>

The usage of $first is simply to differentiate between the first post and the rest of the posts. query_posts uses showposts=8 as parameter, one first post with excerpt and the rest for the list. Also, you should see that the cat-recent-list unordered list is still empty, we’ll get to that next.

5. For the rest of the posts, only display the titles and put them inside an unordered list.

Now, let’s take a look at the code within The Loop:

    query_posts("showposts=8&cat=$catID");
    $first=1;
    $ul=0;
    while (have_posts()) : the_post();
      // Latest post with excerpt
      if($first) {
    ?>
    <div class="cat-most-recent">
      <h4><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h4>
      <div class="cat-list-excerpt">
        <?php the_excerpt(); ?>
      </div>
    </div>
    <?php
        $first=0;
      } // end if
      else {
        if ($ul==0) {
          echo '<ul class="cat-recent-list">';
          $ul=1;
        }
    ?>
      <li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>
      <?php } // end else ?>
    <?php endwhile; ?>
    <?if ($ul) echo '</ul>' ?>
  </li>

And we’re done. Yay! Not too complicated, I hope. $ul is used to add the necessary unordered list tag, and is only added if there is actually more than one post per category.

To recap, here’s the complete code from beginning to end:

<ul id="cat-listing">
<?  foreach ($categories as $cat) { ?>
  <li class="cat-block">
    <h3><?echo $cat->name; ?></h3>
    <?php
    $catID = $cat->cat_ID;
    query_posts("showposts=8&cat=$catID");
    $first=1;
    $ul=0;
    while (have_posts()) : the_post();
      // Latest post with excerpt
      if($first) {
    ?>
    <div class="cat-most-recent">
      <h4><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h4>
      <div class="cat-list-excerpt">
        <?php the_excerpt(); ?>
      </div>
    </div>
    <?php
        $first=0;
      } // end if
      else {
        if ($ul==0) {
          echo '<ul class="cat-recent-list">';
          $ul=1;
        }
    ?>
      <li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>
      <?php } // end else ?>
    <?php endwhile; ?>
    <?if ($ul) echo '</ul>' ?>
  </li>
  <?php } //end foreach ?>
</ul>

6. Apply CSS to display everything in an interesting way.

This is going to be quick. To display it somewhat like MSNBC’s listing, here’s a very basic CSS:

.cat-block {
  width: 500px;

.cat-most-recent {
  width: 200px;
  float: left;
}

.cat-recent-list {
  width: 290px;
  float: right;
}

The general idea is to float the .cat-most-recent to the left, and .cat-recent-list to the right. Give it the necessary margins, paddings, the usual, and you should be right on track.

Closing

That is all for the tutorial. Also note that this code will display every single category, including subcategories. If you take a closer look at MSNBC’s listing, it only shows posts from the parent categories, while the subcategories are displayed as links to the right of the list of posts.

Subcategories on MSNBC category listing

With more code tweaks the same effect should be achievable. Anyways, here’s more references to the WordPress functions being used:

That is all. If you have questions or new ideas, let me know!

16 Responses to “WordPress Theme Tutorial: MSNBC-like Home Page Category Listing”

  1. Thursday Web Links | FUFT

    [...] Play Work Play has a tutorial for adding MSNBC-like category listings to your Wordpress blog’s homepage. [...]

  2. Ptah Dunbar

    interesting way to apporached that idea to create that functionality. Cool

  3. Chris

    I keep getting “Invalid argument supplied for foreach()” on line two of the script. What am I doing wrong?

    Thanks!

  4. Akshay Surve

    Chris,

    Plz add:

    $categories = get_categories();

    before the foreach block in the last listing to make it like:

  5. Justin

    Thanks for this tutorial! This was exactly what I was looking for for a new project and I couldn’t find it anywhere but here.

  6. gamal

    hello. i used your technique on my website and it works like charm. but there is something that i can’t figure out. it doesn’t display the parent categories only like msnbc.com website, but it displays the parent categories with its subcategories. how can i exclude subcategories from showing??!..

  7. Tammy S. Hart

    Awesome, just what I was looking for!!!

  8. Tammy S. Hart

    this will help you get only parent categories listed: http://webmasterweblog.com/wordpress-exclude-subcategories/

  9. ThinkSoJoE

    When I first tried this, I couldn’t for the life of me figure out how to get it to work right, as I was having some crazy problem with the second category excerpt showing up right under the first category links. After playing around for several hours, I figured out the fix: clear the float before the end of the foreach! Works great now, thanks for the great idea!

  10. srhnbr

    This is exactly what I wanted. Thanks
    I do get an error though:

    Fatal error: Cannot access empty property
    on $cat_ID; query_posts(”showposts=1&cat=$catID”); ?>
    what I’m I doing wrong?

  11. Jan Alvin

    Do you have a sample work for this one??

  12. Give your blog a makeover, MSNBC style « TV on Your PC Roundup

    [...] WordPress Theme Tutorial: MSNBC-like Home Page Category Listing (Play Work Play) [...]

  13. LEVI

    This is exactly what I need for my project, and it is so straight forward. However I am doing something absolutely wrong. I can’t get anything to show up. Can you point me in the right direction?

    name; ?>
    cat_ID;
    query_posts(”showposts=8&cat=$catID”);
    $first=1;
    $ul=0;
    while (have_posts()) : the_post();
    // Latest post with excerpt
    if($first) {
    ?>

    <a href=”">

    <?php
    $first=0;
    } // end if
    else {
    if ($ul==0) {
    echo ”;
    $ul=1;
    }
    ?>
    <a href=”">

    <?if ($ul) echo ” ?>

  14. LEVI

    Oops!
    I actually placed your code in my index.php file between the loop which looks like this…
    [?php while (have_posts()) : the_post(); ?]
    ——
    Your Code
    ——
    [?php endwhile; ?]

    Don’t see a thing….

  15. Vitty Library

    Thanks For the Great Tutorial

  16. Chris Lati

    Works great, but how can I get this to work for only one specific category instead of for all the categories on my site?

Leave a Reply

Hello!

My name is Hafiz Rahman. I do standards-based web design and WordPress works. I'm open for new projects, and here's where you can contact me.