If you’ve ever wanted to create dropdown, category-based navigation in your ExpressionEngine website, you’ve probably also wanted to punch a hole in your desk. It’s not easy. Or is it? In this tutorial, I’ll show you how.
Requirements
To follow along in this tutorial, you’ll need:
- An ExpressionEngine website running EE 1.6.x (I haven’t yet tested this in EE 2.0)
- The Subcategories plugin
- To use category URL titles in your links, not category IDs
The Subcategories plugin is available for download on this thread in the EE forums; however, since it’s not clear which version to grab, and since there was a minor bug in the code, I’ve made a corrected version available for direct download right here.
Grab the plugin, save it as pi.subcategories.php, and upload it to your system/plugins directory.
Live Demo
If you’re the visual type (like I am) you probably need to see the menus in action. The demo is pulling from a live EE install on our web server. It may also help to see a screenshot of the category heirarchy.
Template Structure
Once you’ve uploaded the plugin file, you’ll need to create a few templates:
- embeds/navigation
- embeds/subcategories
- embeds/sub_subcategories
- an additional embed for each additional level of subcategories (if you desire more)
For the visuals, here is a screenshot of my templates page.
The embeds/navigation template controls your main, top-level navigation. Embedding this template as I have done is optional; you can also leave your main navigation code in your header template (or wherever it normally appears).
The embeds/subcategories template is only called if a top-level category has any subcategories. It displays a list of, well…subcategories.
The embeds/sub_subcategories template is only called if a subcategory has any subcategories.
You can create as many levels of dropdowns/flyouts as you want by replicating the embeds/subcategories template and naming it something else (like embeds/sub_sub_subcategories).
The Code
In your embeds/navigation template, place the following code:
<ul id="nav">
{exp:weblog:categories parent_only="yes" style="linear"}
<li>
{exp:query sql="SELECT cat_id FROM exp_categories WHERE parent_id = '{category_id}' LIMIT 1"}
<a href="{path='SITE_INDEX'}"{if '{total_results}' > 0} class="fly"{/if}>{category_name}</a>
{if '{total_results}' > 0}{embed="embeds/subcategories" cat_id="{category_id}"}{/if}
{/exp:query}
</li>
{/exp:weblog:categories}
</ul>
If you’re scratching your head about what that all means, here it is:
- First, we use the exp:weblog:categories tag pair to show a list of all categories. We show only top-level categories by using the parent_only=”yes” parameter.
- Next, we output a link to the category and display the name (using {path=’SITE_INDEX’} removes the “category” segment from the URL). The {exp:query} call allows us to add a class of “fly” to anchors that are associated with parent categories. This is useful if you’d like to add styling to your parent categories (see the demo for an example).
- The {exp:query} call also checks to see if your top-level categories have children. If so, call the embeds/subcategories template.
In your embeds/subcategories template, place the following code:
<ul>
{exp:subcategories root_node="{embed:cat_id}"}
<li>
<a href="{homepage}/category/{category_url}"{if '{subcategories_count}' > 0} class="fly"{/if}>{category_name}</a>
{if '{subcategories_count}' > 0}{embed="embeds/sub_subcategories" subcat_id="{category_id}"}{/if}
</li>
{/exp:subcategories}
</ul>
Here is an explanation of the code:
- We passed in the parent’s category ID as cat_id. The subcategories plugin takes this value in the root_node parameter to pull a list of subcategories.
- For each subcategory, output a link. The Subcategories plugin has a neat variable called {subcategories_count}, which lets us replace the SQL query that you see in the embeds/navigation template. If there are subcategories, apply a class of “fly” to the anchor. This lets us style our anchors to indicate that there are more dropdowns/flyouts.
- Lastly, use the {subcategories_count} variable to see if the current subcategory has subcategories of its own. If so, call the sub_subcategories template.
In your embeds/sub_subcategories template, place the following code:
<ul>
{exp:subcategories root_node="{embed:subcat_id}"}
<li>
<a href="{homepage}/category/{category_url}">{category_name}</a>
</li>
{/exp:subcategories}
</ul>
Note how similar this code is to the embeds/subcategories code. The only difference is that we did not check to see if the grandchild categories had subcategories of their own. We can easily do this by adding the following line…
{if '{subcategories_count}' > 0}{embed="embeds/sub_sub_subcategories" subcat_id="{category_id}"}{/if}
…and then creating an embeds/sub_sub_subcategories template. In this way, you can create as many levels of menus as you want.
Enjoy
Adding category based dropdown menus to an ExpressionEngine website doesn’t have to be a drag. This tutorial should get you up and running without trouble; however, if you find bugs or see ways to improve the examples here, let us know in the comments.

Post a Comment