How to Create a Fully Custom WordPress Mega Menu – No Plugins Attached

The mega menu concept has been with us for a while now. With each passing day more and more sites are trying to utilize this function in various ways in order to serve us as much information as possible through, what appears to be, a simple “dropdown” menu. When using WordPress, both clients and developers often end up using some sort of plugin to implement this function. Guess what? We’ll show you how you can implement a custom WordPress mega menu with just a few lines of code and zero plugins.

Before we get down to the coding part, let’s first talk about what exactly we’re going to create since mega menus can be built in lots of different ways. Essentially, we’re going to use a combination of menu locations, menu items, widget areas and widgets. We’re going to have a specific menu location that will hold menu items. Each menu item from that menu location will be able to “host” widgets “within itself” through a dedicated widget area for that menu item. Those widgets can be anything from custom menus, text areas to images and articles.

To kick off with creating our own custom WordPress mega menu – let’s get down to the coding part!

Registering a dedicated menu location

Firstly we need to register a new menu location. The reason for this is we want to have a specific location on the site that will host our custom WordPress mega menu so you, or the client, can add on as many menu items as needed. In order for us to register the new menu location – we’ll open up the functions.php file (assuming you already have a theme on which to work on) and add the following lines of code:

Now let’s add few menu items to our new menu location.


Not all menu items will have widgets attached to them. With this in mind we want to develop a way in which we can distinguish those menu items from those that will indeed host some widgets. There are many ways in which we can do that but let’s keep it simple. We’ll use the “CSS Classes” option. If you don’t see the “CSS Classes” option (field) under your menu items just click the “Screen Options” button in the upper right corner of the window and select the “CSS Classes” option.

Now let’s add the “has-mega-menu” class (feel free to use any class name you wish) to 2 of our menu items that will have a mega menu dropdown attached (don’t forget to click the “Save Menu” button once you’re done).


Dynamic sidebar (widget area) registration

Our custom WordPress mega menu is coming along nicely. Next we want to register new widget areas (sidebars) for each menu item with the “has-mega-menu” CSS class. To do that we’ll create a new function which hooks to the “widgets_init” action. Within that function we’ll iterate over all menu items within a “mega_menu” menu location and in every iteration check if the menu item contains the “has-mega-menu” CSS class or not. If it does, simply create a new widget area for that menu item using the register_sidebar function.

If we now go to the “Appearance -> Widgets” administration interface we should see 2 new widget areas. There’s one for each menu item with the “has-mega-menu” CSS class (“Solutions” and “Company).

Custom WorPress Mega Menu


For the frontend side you can write down a simple loop that will echo all navigation items and all “dynamic sidebars” for those items that have a corresponding widget area.

Keep in mind that you might want to change this code to better fit your own needs but that’s basically it!

You now have a custom WordPress mega menu written with just 25 lines of code and zero plugins installed. Of course, you now need to add widgets to your brand new mega menu. You might want to use stock widgets like “Text” or “Custom Menu” or develop your own for the mega menu purpose. Remember, you can always shake things up and optimize by serializing and storing the information on which menu items should have widgets attached to them. This avoids the wmpp_init function loop from executing for each single request you get and you could even add a custom option to the menu item(s) like a checkbox which defines if there is a widget area for that very menu item.

Job done! Your custom WordPress mega menu is ready to roll

Got any questions or suggestions? We would love to hear your feedback and hear how you’re getting on! If you like this post, why not check out some of our other posts on WordPress tips and trick here.

About Domagoj Gojak

  • Alaa Samy

    Thank You So Much For This Tutorial.
    but every widget is displayed under its menu item , how to hide all widgets and display only when hover the menu item, I tried using CSS but it didn’t work.

    • DomagojGojak

      You are very welcome! Be sure to check some of our other blog posts which might help you a lot as well. Also, we have much more blogs in store for the future, so keep your eyes open and subscribe to our newsletter. 🙂

  • Wow, this is insanely more simple that what i did (ie. go into a custom menu walker, etc.)

    • DomagojGojak

      Glad you like it. We tried to keep the procedure as simple as possible. 🙂

  • deondazy

    Wow! This just saved me a huge amount of time, it’s very simple and straight to the point. Thanks Domagoj

    • DomagojGojak

      Hey, that’s why we write this stuff. 😉 I’m glad that you were able to put this to a good use. 🙂

  • Nico

    Very nice idea but this approach misses active class names as well as sub-menu handling.

    • DomagojGojak

      Hi! Yes, we didn’t include the class names within the mega menu wrapper but that can easily be added by extracting from the $item classes property. When it comes to menu widget rendering WITHIN the mega menu (or any other widget for that matter) all classes as well as all other default properties will be included because of the fact that we are rendering widgets and not some custom HTML (of course, you can choose to render your own custom widgets but then you would need to handle the rendering of the classes and active menu items on your own).

      Thank You for the feedback! 🙂

  • Janneman Human

    Nice and easy. Did you try to integrate this with a walker?

    • DomagojGojak

      Not quite but if we give it a shoot you will be one of the first to know. 😉

  • jude

    Really nice and Straight. but please I have completed your instruction but my mega menu is just displaying like a list(under the header).
    your help will be appreciated.

  • Hey – this is a brilliant and simple solution! However, the render code outputs a list and does not take submenus into account. Could you provide an example of how that could be done?

    No Submenu
    Submenu 1

    Submenu Item 1
    Submenu Item 2
    Submenu Item 3

    Submenu 2

    Submenu Item 1
    Submenu Item 2
    Submenu Item 3

  • Very nice idea. Clean and fast solution. Congratulations.

  • saiful

    Hi Gojak,
    Thanks for your great tutorial. It is ok and generate dynamic sidebar. But the widgets are not appear in right place in . Feel free please give me solution how can i fix it.


  • meno

    Hi Gojak,
    Thank you very much for this great tutorial.
    But can you help us to add css to see this menu in action
    Can we create sub menus in this mega menu, that hover category link to load posts by ajax ?

  • Ryan Kidd

    Awesome article. For me, this was easier than using a plugin. Thanks Domagoj!

  • Johnny

    Great article. It’s a really good idea to combine widget and default menu to create the awesome mega menu. Thanks for sharing Domagoj!!!

  • jfarruggio

    Do you have a solution to prevent the sidebar from being rendered as a sibling ? It should be a child of li div.mega-menu.

    My markup is identical to your tutorial.

    • Thomas Dexter

      This is because wordpress is outputting the widget with a wrapper and then the browser is moving it to the same DOM level as the other ‘s .. To stop wordpress from wrapper it with you need to set the before/after params when you register the sidebars like so:

      register_sidebar( array(
      ‘id’ => ‘mega-menu-widget-area-‘ . $item->ID,
      ‘name’ => $item->title . ‘ – Mega Menu’,
      ‘before_widget’ => ”,
      ‘after_widget’ => ”,
      ) );

  • Pamela Muise-Green

    This is a cool tutorial but the actual rendering of the menu doesn’t work (as a couple of people have said below). Would be really cool if you could update the code so that the result has a structure more like this:


  • jacobdubail

    Great article and jumping off point. I’d recommend using a Custom Nav Walker to output the menu and widgets. That way you preserve all of the class names for the top level menu items.

  • Thomas Dexter

    For those having issues with wordpress outputting an <li> around the widget and then the browser misplacing it in the DOM change your register_sidebars to the following:

    register_sidebar( array(
    ‘id’ => ‘mega-menu-widget-area-‘ . $item->ID,
    ‘name’ => $item->title . ‘ – Mega Menu’,
    ‘before_widget’ => ”,
    ‘after_widget’ => ”,
    ) );

    • Мөнхбаяр Шд

      Great, Thanks Thomas

      • Thomas Dexter

        No problem.

        • Мөнхбаяр Шд

          One more question. Is it possible? Could I integrate that mega menu with the Bootstrap Navwalker? 😀

          • Thomas Dexter

            Whats the code for that look like? Should be possible. Can you post it here or link to it on github?

          • Мөнхбаяр Шд
          • Megan Simpson

            I would also love to know if this can be integrated with Bootstrap Navwalker. That would be very handy as I use Bootstrap for all my custom themes.

          • jaycbrf4

            I was just going to comment the same thing.

  • Raja Mohammed

    Great One 🙂 Helped me resolve my mega menu solution . Thanks a lot.