Creating Category-based Navigation with Description (a la Grid Focus)

UPDATE 24 December 2009:
Changed the main code on line 11 from $get_cat_id = '/cat-item-[0-9]+"/'; to $get_cat_id = '/cat-item-[0-9]+/'; (without double quotes). This is to deal with the additional “current-cat” class added automatically when a category is currently displayed.

One of Grid Focus theme‘s most prominent feature is its navigation bar with link name and description, depicted below in its modified version at Logo Design Love:

logodesignlove-nav

These navigation links (and their descriptions) are hard-coded into the theme, though, so they’re a little less flexible. For a theme I’m currently working on, I had an idea of creating a navigation like this but using a list of categories instead. The description text will then be pulled from each category’s description, which can be set directly via the Dashboard menu at Posts > Categories, therefore preventing users from having to mess with PHP file:

WordPress add category description panel

The PHP Code

When displaying a list of categories, the function to use is obviously wp_list_categories. However, that function only allows us to use the category’s description as a title property of the anchor link (and nowhere else), for example:

<li class="cat-item cat-item-3">
  <a href="http://wplover.com/category/development/" title="Hack Away">Development</a>
</li>

No luck there, because for our category-based navigation to work, we need to wrap the description inside a span tag:

<li class="cat-item cat-item-3">
  <a href="http://wplover.com/category/development/" title="Hack Away">Development<span class="cat-desc">Hack Away</span></a>
</li>

Our solution then, is to create a little hack where we manipulate the output of wp_list_categories() and inject the descriptions there.

Here’s my code, which should go into functions.php in your theme:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// Create a modified output of wp_list_categories where the categories description
// is added inside a span tag within the link like so:
//<li><a title="Category Description" href="#">Category Name<span>Category Description</span></a></li>
function list_cats_with_desc() {
  $base = wp_list_categories('echo=0');
 
  // wp_list_categories adds a "cat-item-[category_id]" class to the <li> so let's make use of that!
  // Shouldn't really use regexp to parse HTML, but oh well.
  // (for the curious, here's why: http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 )
 
  $get_cat_id = '/cat-item-[0-9]+/';
  preg_match_all($get_cat_id, $base, $cat_id);
 
  // Let's prepare our category descriptions to be injected.
  // Format will be <a>category-name<span>category-desc</span></a>
  $inject_desc = array();
 
  $i = 0;
  foreach($cat_id[0] as $id) {
    $id = trim($id,'cat-item-');
    $id = trim($id,'"');
 
    $desc = trim(strip_tags(category_description($id)),"\n");   // For some reason, category_description returns the
                                                                // description wrapped in an unwanted paragraph tag which
                                                                // we remove with strip_tags. It also adds a newline
                                                                // which we promptly trim out.
    if($desc=="") $desc = "Add Description";
 
    $inject_desc[$i] = '<span class="cat-desc">' . $desc . '</span></a>';
    $i++;
  }
 
  // Now we inject our descriptions
  $base_arr = explode("\n", $base);
 
  $base_i = 0;
  foreach($inject_desc as $desc) {
 
    // We check whether there's an occurence of "</a>"
    while(strpos($base_arr[$base_i], "</a>") === false) {
      $base_i++;
    }
 
    // If we find one, inject our description <span>
    $base_arr[$base_i] = str_replace("</a>", $desc, $base_arr[$base_i]);
 
    $base_i++;
  }
 
  $base = implode("\n", $base_arr);
  echo $base;
}

After that, calling this list_cats_with_desc() function anywhere in your theme will result in something like this:

<li class="categories">Categories
  <ul>
	<li class="cat-item cat-item-3"><a href="http://wplover.com/category/development/">Development<span class="cat-desc" title="Hack Away" Hack Away</span></a></li>
	<li class="cat-item cat-item-4"><a href="http://wplover.com/category/themes/" title="Pretty Ones">Themes<span class="cat-desc">Pretty Ones</span></a></li>
	<li class="cat-item cat-item-5"><a href="http://wplover.com/category/news/" title="Get Updated">News<span class="cat-desc">Get Updated</span></a></li>
  </ul>
</li>

Notes Regarding the Function

  • For this to work, wp_list_categories() must output the links in a list style format. On line 5 of my function above, you can tweak the parameters more (say, to exclude some categories), but the ‘style’ parameter must remain ‘list’. Refer to the Codex for more info about wp_list_categories’ parameters.
  • If a category does not have any description, it will use the default text “Add Description” (line 27 above). Change this to anything you wish. Ideally for our navigation, every category must have a description.

The CSS

After we get the HTML list formatted nicely, the last thing to do is to CSS it. Borrowing and tweaking from Grid Focus’ code, you can use something like this as an example:

.categories li a {
	font-weight: bold;
	letter-spacing: 1px;
	text-transform: uppercase;
	float: left;
	display: block;
}
.categories li a span.cat-desc {
	color: #888;
	font-size: 0.9em;
	font-weight: normal;
	text-transform: lowercase;
	display: block;
}

The most important thing is to throw a display:block for the .cat-desc so the description stand on its own underneath the category name but still clickable at the same time.

The End

Anyway that’s it! Let me know if you have any thoughts to share!

You may also like...

10 Responses

  1. Daus says:

    For a theme I’m currently working on, I had an idea of creating a navigation like this but using a list of categories instead.

    Are you going to release it for free? *hahah modal gratisan.

  2. Hafiz Rahman says:

    Are you going to release it for free?

    Yes, hopefully soon :)

  3. Kazaf says:

    Great tutorial! Exactly what i’ve been looking for.
    Thanks

  4. memphis says:

    what if i using a hightlight navigation, and i still wanna use this technique. how do i do with it?

    could tell me more specific detail?

    thx

    great tut BTW

  5. Alen says:

    Thank You ! This is exactly what I needed ! I was searching all over the internet for this solution, and I nearly gave up …
    Thanks a bunch, again !

  6. Travis says:

    Just what I was looking for. Perfect.

    Thanks so much!

  7. Tory Athay says:

    Some interesting information on here. Slightly off topic but I am so excited !. I saw Cats The Musical for the first time and the music and also the dancing is incredible. It is definitely an emotional journey that all the audience gets involved with !. ‘Cats’ will make you laugh and smile and touch certain areas in your heart. Everybody left the theater singing, content and uplifted. If you get a chance to go and see ‘Cats’ I really recommend it.

  8. Miles says:

    Great code, just what I was looking for. But would it possible to have this output the index page as the first link?

    Thanks for putting this together.

  9. I am really thankful to this topic because it really gives useful information -‘”

  10. It is a Fantastic post! I hope you not mind.I published an excerpt on our website and linked back to your blog site for people to read the full version. Thanks for your advice.

css.php