WordPress isn’t much different, the native menu functionality is powerful and versatile enough to give us with exactly the HTML we’d require, plus a few more options for providing a better user experience to our users. The aim of this post is to take you through those and provide a complete solution on how to style a native WordPress navigation menu.
Adding a WordPress menu to our website
Displaying a nav menu on your WordPress site is generally very simple, it only takes a couple of lines:
Then all you have to do is go through the usual process of creating a menu and adding items to it via the admin dashboard.
For this tutorial we’ll assume our menu’s structure is as follows:
├── Home ├── Blog | ├── News | ├── Sports | ├── Fashion | | ├── Article #1 Title | | ├── Article #1 Title | ├── Business ├── About └── Contact
So basically a menu of three levels (our final styles will support infinite nested levels). This would produce roughly the following markup:
I said “roughly” before, and that’s because although the actual HTML structure will remain the same throughout our website, WordPress will add very specific classes depending on what page we’re currently viewing.
We need to keep in mind that WordPress adds the following three important classes to the menu’s <li> elements with the following rules:
- .menu-item-has-children: Menu items that contain sub-items (just like “Blog” and “Fashion” in our example).
- .current-menu-item: Menu items that correspond to the currently viewed page (so in our example we just opened the homepage as “Home” contains this class).
- .current-menu-ancestor: Menu items that are ancestors (parents, grandparents) of the menu item which corresponds to the currently rendered page.
We’ll very soon see how to use these classes in our stylesheets.
WordPress also adds a few other classes that generally do not concern us in a normal menu, but can become useful in very specific use-cases so be sure to check them out.
Giving the menu some structure
With the markup in place it’s time to start styling our menu. We’ll be using Sass instead of vanilla CSS. Sass comes very handy here, especially in styling menus where there’s a lot of nesting involved. It’s extra useful because (as with most things in WordPress) we need to style everything on our menu under its main class namespace (.navigation-main). This will prevent our styles from “bleeding” out to other potential menus we might have in our theme.
In general, when I write styles for a navigational component with a complex functionality I like to split styles into blocks “structure/functionality” and “presentation/appearance” styles, even if that means that I have to be a bit more verbose or even duplicate some selectors. I’ve found that it provides a clear separation of concerns and becomes a much more maintainable paradigm, especially when the component’s presentational requirements become very complex (think animations, different colors for each sub-item, etc). We’re not going to deal with that kind of stuff right now, but it’s a good practice to have in mind when the CSS concerns are so cleanly separated in a particular isolated component such as this one.
This is all it takes to imbue the functionality of a standard navigation menu, and support infinite nested levels. We absolutely position all sub-menus, offset them out of screen (we don’t set their display property to “none”) and we reposition them on hover making them visible.
Here’s how this all looks:
Try hovering over “Blog”, and then “Fashion”.
It’s kinda ugly though, so let’s make it a bit prettier.
Adding appearance and visual clues to the menu
Pretty basic stuff, some background and link colors:
And here’s how it looks now:
Although our menu is starting to look good it’s missing a couple of things which are quite important for a good user experience.
First of all, it would be nice if while the user hovers over different nav items their parents and ancestors remain highlighted. It helps with visual identification of the current hovered path and it just looks better, so let’s fix that with the following extra selector:
Secondly, we must highlight the nav items which correspond to the currently viewed page. That means that, if a user is at “Home” we should highlight the “Home” item, and if a user is viewing “Article #1” the menu should highlight all its ancestors up to and including “Blog”.
Here’s where the classes we mentioned before come into play, and it’s very simple to handle the above scenarios:
Check out how “Home” now remains active and how if you navigate all the way through “Article #1” its ancestors will also stay highlighted:
Adding visual clues for items with children
It’s also a standard good practice to provide a visual clue (such as an arrow) for items with nested sub-menus. The tricky part here is that items belonging to the first level (main menu) should have arrows pointing down, while the rest should point right. As a final step let’s see how we’d go about this:
Note that I’m creating CSS triangles with the border trick but you’re free to use whatever you wish, e.g. FontAwesome icons (fa-angle-down is a good choice).
And the result:
Pretty good! Looks like we’re all done with our menu, perfectly styled and ready for deployment.
Going the extra mile: Making the menu accessible
This toggles a class on a menu item every time we focus on its link. This way we can simply alter our CSS to display the sub-menus when that class is present:
And we’re done! Let’s look at a complete example with more nested levels and the current menu item on a lower level than the main menu. Try hovering over and tabbing through and it should all work great!
Let us know in the comments how you prefer to style your WordPress menus or any tips and tricks you might have up your sleeve, and, oh! if you’d also like to convert your menu into a mobile drawer for mobile devices we’ve got you covered :)