How to Code an Awesome Categories Menu for Your WordPress Site

Sometimes it’s good to ditch the default functions for components and create our own stuff. WordPress has great features for category listing but when it comes to customization we need to dig a little deeper on its functions.

Today we’ll see how to do an awesome categories menu, based on Pawel Kadysz’s awesome menu design.

We’ll see alternatives to WordPress wp_list_categories functions that allows full customization. Also we’ll see how to do it with clean CSS and a little jQuery for final touches to make it smoother.

So, are you ready to rock?

The Final Look

How to Code an Awesome Categories Menu for Your WordPress Site

This is what we get by the end of this tutorial. Highlighted item is the hovered one and all those categories will come from WordPress. You can Download source files or visit the live demo.

#1 – Slicing and adjusting

Before getting into the coding part we need to slice the psd we downloaded, right? Actually no (I know, I know, the sub title is wrong). We’ll use CSS3 for those subtle effects so the only image there will be the background image.

We’ll need to adjust the background image to make it tileable. Each developer does it his own way, what I do is duplicate the layer, invert it vertically and delete the top part for the inverted layer with a smooth eraser. Then I flatten the result and do same thing horizontally.

How to Code an Awesome Categories Menu for Your WordPress Site

You can just download the final result from the source files.

#2 – PHP (and, why not, HTML5)

When it comes to a categories listing we often just use wp_list_categories, in the best case add a few CSS rules to make it better but we just ignore all the possibilities of using better markup and completely custom menus.

Here we’ll use a standard HTML menu and for categories listing we’ll use the get_categories() function. It works pretty much same as get_posts, returning a lot of data on our categories but with no markup or styling at all, it’s just a PHP object.

Here is our main code to get the menu:

<ul class="mainNav">
	<li><a href="#">Home</a></li>
		<a href="#">Categories</a>
		<ul class="submenu">
			$args = array (
				'hierarchical ' => 0
			$cats = get_categories( $args ); //meooowww!!

			foreach ($cats as $cat) {
				echo '<li><a href="' . get_category_link( $cat->term_id ) . '">'.$cat->name.'<span class="number">'.$cat->count.'</span></a></li>';
	<li><a href="#">Archives</a></li>
	<li><a href="#">Search</a></li>
	<li><a href="#">Contact</a></li>

As for our demo this is the HTML output after processing this function:

	<ul class="mainNav">
		<li><a href="#">Home</a></li>
			<a href="#">Categories</a>
			<ul class="submenu">
				<li><a href="#?cat=1">Tutorials<span class="number">15</span></a></li>
				<li><a href="#?cat=2">Inspiration<span class="number">5</span></a></li>
				<li><a href="#?cat=3">Roundups<span class="number">8</span></a></li>
				<li><a href="#?cat=4">HTML and CSS<span class="number">7</span></a></li>
				<li><a href="#?cat=5">Freebies<span class="number">25</span></a></li>
				<li><a href="#?cat=6">Workspaces<span class="number">4</span></a></li>
				<li><a href="#?cat=7">Apps<span class="number">9</span></a></li>
				<li><a href="#?cat=8">News<span class="number">13</span></a></li>
		<li><a href="#">Archives</a></li>
		<li><a href="#">Search</a></li>
		<li><a href="#">Contact</a></li>

Now we have our raw material. Let’s make it prettier.

#3 – CSS3, gradients, text shadows…

To avoid crazy browser default values, we’ll use a CSS reset. Ok, now we need to add that wooden background and position our main nav. Also we’ll use the CSS gradients to avoid using images. This is the CSS to get this working:

body {
	background: url(background.jpg);
.mainNav {
	position: relative;
	margin: 100px auto 0;
	width: 500px;
	height: 50px;
	font-family: Arial, Verdana;

Now we need to style our links. Since our subitems are also links we need to target our rules for the top ones and then create specific rules to the submenu items, which is easier than use general rules and overwriting them all every time.

We’ll use also CSS gradients for our items. Unfortunately we still need a lot of vendor prefixes to get those items working, but their syntax is pretty similar from one to another. And the final touches will be done with text shadows to avoid using images at all:

.mainNav > li > a {
	display: block;
	padding: 20px 21px 18px;
	font-size: 12px;
	line-height: 100%;
	color: #666666;
	text-decoration: none;
	text-shadow: 0 1px 0 #f4f4f4;
	text-transform: uppercase;
	border-top: 2px solid #f8f8f8;
	border-right: 1px solid #e9e9e9;
	border-bottom: 1px solid #e5e5e5;
	border-left: 1px solid #afafaf;

	background: -moz-linear-gradient( top, #dddddd, #cdcdcd );
	background: -webkit-linear-gradient( top, #dddddd, #cdcdcd );
	background: -o-linear-gradient( top, #dddddd, #cdcdcd );
	background: -khtml-linear-gradient( top, #dddddd, #cdcdcd );
	background: -ms-linear-gradient( top, #dddddd, #cdcdcd );
	background: linear-gradient( top, #dddddd, #cdcdcd );
	background-color: #dddddd;
	.mainNav a:hover,
	.mainNav .hover > a {
		border-top-color: #3F3F3F;
		border-bottom-color: #272727;
		color: #ffffff;
		text-shadow: none;

		background-color: #2a2a2a;
		background: -moz-linear-gradient( top, #2c2c2c, #272727 );
		background: -webkit-linear-gradient( top, #2c2c2c, #272727 );
		background: -o-linear-gradient( top, #2c2c2c, #272727 );
		background: -khtml-linear-gradient( top, #2c2c2c, #272727 );
		background: -ms-linear-gradient( top, #2c2c2c, #272727 );
		background: linear-gradient( top, #2c2c2c, #272727 );

As you can see, this CSS will give a nice divisor between elements but it won’t look good for the first and the last items, so we’ll remove this styling for them:

.mainNav > li:first-child a {
	margin-left: -1px;
	border-left: none;
	border-radius: 8px 0 0 8px;
.mainNav > li:last-child a {
	padding-right: 25px;
	border-radius: 0 8px 8px 0;
	border-right: none;

Now we’ll style our submenus. We need to position it as absolute so it won’t affect the rest of our main items. Also we have a specific styling for our links under submenus. This CSS will get you there:

.submenu {
	position: absolute;
	padding: 15px 0 20px;
	width: 350px;
	background-color: #2a2a2a;
	background: -moz-linear-gradient( top, #272727, #181818 );
	background: -webkit-linear-gradient( top, #272727, #181818 );
	background: -o-linear-gradient( top, #272727, #181818 );
	background: -khtml-linear-gradient( top, #272727, #181818 );
	background: -ms-linear-gradient( top, #272727, #181818 );
	background: linear-gradient( top, #272727, #181818 );
	.mainNav .submenu a {
		position: relative;
		float: left;
		padding: 8px 0;
		margin: 0 0 0 16px;
		width: 150px;
		color: #666666;
		font-size: 10px;
		text-decoration: none;
		text-shadow: none;
		text-transform: lowercase;
		border: 0 none;
		border-bottom: 1px solid #333333;
		.mainNav .submenu a:hover {
			margin-top: 0;
			color: #ffffff;
			border: 0 none;
			border-bottom: 1px solid #333333;
			background: transparent none no-repeat;

#4 – jQuery touch

Now that we’ve got our pretty menu we need to hide it when users have JavaScript enabled and also add the proper bindings so we’ll have the hide / reveal effect.

To make things easier we just got a CDN copy of jQuery so we don’t even need to download it (more on this technique later!):

<script type="text/javascript" src=""></script>

We’ll add our script tag after everything to improve performance. You may be aware that we need to use $(document).ready(); to avoid triggering jQuery before the DOM is actually ready (doh!). But we can also use this great shortcut:

		/* your code here! */

This is pretty much same as $(document).ready(); but it’s far easier to remember, isn’t it?

We’ll hide our submenu. This is pretty easy, this line will do the job:


Now, we need to show the submenu when we hover its parent. Since we already selected the submenu item we can just make use of jQuery chaining and go up in the DOM tree with the “parent()” function.

Now, instead of using the hover function, we’ll use the on, and a mouseenter / mouseleave binding since the hover is just a shortcut for this. This is the corrected line to get it working:

$(".submenu").hide().parent().on('mouseenter', function() {
	$this = $(this);
	if ( ! $this.hasClass("hover")) {
}).on('mouseleave', function() {
	$this = $(this);
	if ( $this.hasClass("hover")) {

Notice that we’ve made use of caching also, so our performance will be a little bit better than if we called $(this) twice for each block.

How to Code an Awesome Categories Menu for Your WordPress Site

[Note: the code in this section for adding jQuery is used for the HTML/CSS demo. For use in WordPress themes it is recommended that you use wp_enqueue_script().]

That’s all!

So, what do you think about it? Do you have a better idea to implement this awesome menu? What about idea for future articles? Don’t be shy and let us know via comments!

View the demo | Download the source code

About the Author:

I’m a WordPress and FrontEnd (HTML5, jQuery, CSS3) specialist from Itajubá, Brasil. I just love writing about obscure topics, doing some cool stuff and helping people out there.

Follow Rochester: Website | Twitter | YouTube channel

Looking for hosting? WPEngine offers secure managed WordPress hosting. You’ll get expert WordPress support, automatic backups, and caching for fast page loads.

7 Responses

Comments are now closed on this post.

  • Antunes, August 2, 2012

    Very good this tutorial, I want to ask a question, I want to create a category with subcategory example I created a category and want to add subcategories to this category dynamically. In the example you show all category that agent will add it to the sub, just want to send to the sub-category that I choose. hugs and hope your answer.

  • amit, June 1, 2012

    hat is a great looking menu

  • Rochester, May 24, 2012

    @Josh, @Brandon
    Hi guys!

    That’s because of the stop() item. I guess it’s better to keep it this way, otherwise if you keep hovering too fast it’ll be fading in / out even after you stopped hovering.

    We can fix it with a little more complex rule which will include testing if the class ‘hover’ is still there and then targeting the right animation (go back to fadeIn or stop fading out).


  • Josh, May 24, 2012

    @Brandon I have the same bug “When you hover over it as it fades out it does not come back to full. Is there a way to fix this?”

    Any ideas Rochester? :)

  • Bradley, May 23, 2012

    That is a great looking menu and simple to do with this tutorial, nice work!

  • Akos Fintor, May 22, 2012


    I prefer video tutorial but this one with the snapshot was pretty cool too.
    thanks for the share!

  • Brandon, May 21, 2012

    When you hover over it as it fades out it does not come back to full. Is there a way to fix this?