How to Make a Drop-Down Menu in WordPress

Final product image
What You’ll Be Creating

Navigation menus are having a bit of a moment in the spotlight. From burger menus for mobile through mega menus for stores to sticky menus for enhanced user experience, there’s a great choice in the way you can present your navigation menu in your WordPress site.

But what if you want to create a straightforward menu with a few top-level items and some more items that drop down from them when the user hovers over them?

Before you start getting into coding advanced menus like mega menus and burger menus, it’s a good idea to learn how to create a drop-down menu. This will come in useful on more sites than you might imagine (not every site needs a fancy menu), and it will give you the foundation you need to start building more advanced menus.

In this tutorial, I’m going to show you how to create a drop-down menu in your WordPress theme, using CSS to target the HTML that’s output by the WordPress menu function. This is designed for using in a theme you’re coding yourself, and not for a third-party theme, which will already have its own menu. However, if you’re working with a third-party theme whose menu isn’t drop-down and you want to add this, then you’ll need to create a child theme and add your menu code to that.

What You’ll Need

To follow along with this tutorial, you’ll need:

  • a development installation of WordPress
  • a theme you’re coding yourself, or a child theme of a third-party theme if you want to modify the menu
  • a code editor

WordPress’s Built-in Menu Functionality

The first thing you’ll need to understand is how WordPress generates menus. Unlike for static sites, menus aren’t hard-coded into your site. Instead, WordPress uses a PHP function to query the database and fetch navigation menu items, then display them in the correct structure.

Each item in your navigation menu is actually a post in the wp_posts table in your database—not a normal post, but a special kind of post that’s used just for navigation menu items, with its own metadata including the text to be displayed and the target of the link.

In your theme, open up the header.php file. You should be able to find this line:

Your function may look a little different depending on the parameters, but let’s break down the example above and see what each element does:

  • wp_nav_menu() is the function that fetches a navigation menu and outputs it.
  • The parameters are then wrapped in an array.
  • container_class is the CSS class that will be given to the container in which the menu is wrapped. In this case, it’s main-nav. That’s what we’ll be targeting with our CSS later on.
  • theme_location => primary tells WordPress that this is the primary navigation. If I create a menu in the admin screens and check the Primary box, then this menu will be used for this spot in the code.

Sometimes you might want to add a navigation menu elsewhere in your theme, for example in the footer, in which case you don’t want to use theme_location => primary. You can only use this for one menu. But you may want to use additional parameters, which you can find in the WordPress handbook page on wp_nav_menu().

Here’s the checkbox for the primary navigation in the Menus admin screen:

The primary navigation checkbox in the Menus admin screen in WordPress

Code Output by the wp_nav_menu() Function

Before we can add CSS to create the dropdown menu, it helps to be familiar with the code that WordPress generates for menus.

Here’s a typical menu for a small business, shown in the Menus admin screen:

Menu in menus admin screen with top level items and second level items

Now here’s the HTML output for that menu:

If you examine that code, you’ll see that it consists of:

  • A div with the main-nav class, defined in the wp_nav_menu() function.
  • Inside that, a ul with the ID menu-navbar and the class menu. These are defaults defined by WordPress.
  • Inside that, a number of li elements, each with the class of menu-item menu-item-type-post_type plus other classes specific to the type of post that the menu item leads to and the state of that menu item at the time. Each one also has a unique ID with a number corresponding to the post ID of the navigation menu item in the database.
  • Inside one of the li elements is another ul with its own li elements inside—the second level menu items. It’s this that we want to drop down when the user hovers over the top level menu item.

Coding the CSS to Create the Drop-Down Menu

So now we know what’s being output by WordPress, we can determine which elements we want to target with our CSS.

We want to achieve a couple of things:

  • When the page is opened, the second-level menu items are hidden.
  • When the user hovers over a top-level item, the second-level items below it appear.

Hiding the Second-Level Items by Default

In your theme’s stylesheet, start by hiding the second-level items by default.

Add this:

This will hide the ul element inside another ul element inside the main-nav element. It won’t hide a top-level ul element however, as it requires one ul to be nested inside another ul inside the menu.

Now if you open the page and try to view the second-level items, it won’t be possible—they’ll be hidden. Let’s fix that.

Making Second-Level Items Appear on Hover

Now we need to ensure that the ul nested inside the top-level li will be displayed when the top-level li is hovered over.

Add this to your stylesheet:

Now when you hover your mouse over the top-level item, the list beneath it will appear. But you’ll find that it won’t display the way you want it. Specifically, it will be pushing down the content below the menu. We want it to appear as if it’s floating on top of the content. To fix that, we need to add some layout styling to our ul ul element.

Adding Layout Styling to the Second-Level List

Open you stylesheet and find the line with display: none in it. Edit it that block to add layout styling:

You also need to give the top level list item relative positioning:

Let’s take a look at what that code does:

  • position: absolute gives the second-level list absolute positioning, taking it out of the flow of the elements in the page. For the higher-level item, position: relative puts the top level list in the flow of the page and allows for an absolutely positioned element to be placed inside it.
  • top: 3em positions the top of the list relative to the top of the element it’s inside, namely the top level list item. This 3em value reflects the height of the top-level navigation bar. Edit yours if your top-level navigation has a different height.
  • left: 0 places the list to the left, relative to the item above it.
  • z-index: 99999 defines where the element sits in a three-dimensional model of the page. A high value of 99999 ensures that it is displayed on top of everything else.
  • The remaining code gives the list width and also adds display styling to it, including a shadow to make it look as if it’s on top of the page.

Now let’s take a look at what we see when we hover over the top-level item:

It works! When I hover over the top-level item, the drop-down menu is now displayed.

Drop-Down Menus are Useful for Small Multi-Level Menus

When your site needs a menu with multiple levels, but you don’t need a lot of links outside your top-level menu, a drop-down menu is the simplest way to achieve this. The site I’ve used to demonstrate this only has one item in its menu with other items below it, and there are only three of those. Using a mega menu would be overkill, and a single-level menu wouldn’t allow me to display everything I want.

Being able to add a menu like this to your themes will give you more flexibility with your menus and enhance user experience. And you can do it with just a few lines of CSS.

While you’re here, check out some of our other posts on how WordPress menus and navigation.