In this tutorial, I’ll show you how to create the following dropdown mega menu using the flexbox layout module:
This is not an easy layout, so we will create it using the following steps:
Firstly we mark up and style the main menu bar.
We then create a flexbox template for the mega menu with the sections you can see on the screenshot above: Holiday types, Holiday packages, Our services, Last minute offers, and Trending destinations.
We insert the content (images, <ul> lists, icons) into the template.
Next, we align the items inside each section.
We remove the template’s helper styles (background colors and borders) from the CSS.
We add the hover rule that will display the mega menu when the user hovers over the Holidays menu.
If you want to test our flexbox mega menu before getting started, check out the following demo:
Developing a Mega Menu for WordPress?
UberMenu (WordPress Mega Menu Plugin) is one of the biggest-selling items on CodeCanyon and does absolutely all the heavy lifting for you if you’re building a mega menu for WordPress. Take a look (and then return to the tutorial, obviously!)
1. Create the Main Menu Bar
The main menu bar consists of five items: Home, Holidays, About, Blog, and Contact. The dropdown mega menu will belong to Holidays, while the other menu items will just stand on their own. Here’s the HTML that marks up the main menu bar (but not the mega menu yet):
In the CSS, we’ll now define the basic styles and colors. We’ll also turn the .menu element into a flex container so that the menu items can line up in a straight row. By adding the center value to the align-items property, we center each item vertically inside the flex container, too:
We also set the flex: 1; rule on the menu items to make them span across the entire width of the flex container and share space among them equally. If you want to know more about how the flex shorthand works, check out my article on flexbox sizing properties:
Below, you can see how the main menu bar looks now:
2. Create a Template for the Mega Menu
To get the layout of the mega menu right, we create a template first, then populate it with content. As our mega menu consists of multiple levels of unordered lists, it’s much easier to start by laying out the main sections. This is how our HTML changes:
As you can see, .submenu has two parts: .submenu-top for the four list-based sections (Holiday types, Holiday packages, Our services, Last minute offers) and .submenu-bottom for the image-based Trending destinations. They will be two separate flex containers so that we can apply different flexbox sizing and alignment rules to each.
Below, you can see the layout we want to achieve using flexbox. I’ve added colors and borders to the template so that you can see how the different flex items relate to each other (the template uses the HTML above):
The first row is the main menu; we already created and styled this in Step 1. The second row is .submenu-top which is a flex container that lets the items take as much space as they need based on their content (content-awareness). And, the third row is .submenu-bottom which is a flex container that divides the space equally between the items.
Beyond this, we position .submenu relative to .menu using the position, top, and left properties. As .menu is 60px high, we move .submenu 60px down relative to its position. The CSS below also contains the aforementioned styles belonging to .menu and .menu-item, however it adds position: relative; to .menu, too.
We display the two submenus (.submenu-top and .submenu-bottom) as a column-based flex layout by adding the flex-direction: column rule to .submenu. At the same time, both .submenu-top and .submenu-bottom are row-based flex layouts for their own child elements as well. We don’t add flex-direction: row; to the code because this is the default value for flex-direction, we just set the display properties of .submenu-top and .submenu-bottom to flex.
As we want to make .submenu-top content-aware, we need to allow flex items to stretch as much as they need, so we don’t define the flex property here (it will use its defaults). However, we want the items to properly line up next to each other, so we add justify-content: space-around; to .submenu-top. In this way, the positive space will be evenly distributed between the flex items.
The layout of .submenu-bottom is identical to the layout of the main menu (.menu). So, we use the flex: 1; rule on the items to make them equally share the entire width of the flex container among each other.
In the demo below, you can see how the different sections of our mega menu line up compared to each other:
3. Insert Content into the Template
In this step, we won’t do anything but insert the final content into our mega menu template. In .submenu-top, each flex item gets its own unordered list, while .submenu-bottom is just one unordered list for the four trending destinations:
In the HTML above, I used Font Awesome icons and pulled images from Lorem Picsum. If you look at the screenshot below, you will immediately understand why we began by creating the template:
The items already line up in the layout we want. Now we only have to do some minor alignment work, then remove the helper colors and borders of the template (unless you’re into the whole brutalist aesthetic?!).
In this step, we won’t touch the HTML, just fix the smaller issues of the layout using CSS. The first thing I see when I look at the image above is that the Holiday packages section in .submenu-top is too wide compared to the other items. This could get worse if we have even longer descriptions. So, it’s reasonable to add a max-width value to the flex items in .submenu-top, for example:
By controlling the width of the flex items, our mega menu looks much nicer:
Now to apply a couple of tiny adjustments to the CSS. We turn each list item of the first and second columns into a separate flex container. This means four tiny flex containers in the Holiday types section and three tiny flex containers in Holiday packages.
We use this solution to force the elements to decently line up next to or below each other in the following way:
in the Holiday types section, we use align-items: center; to show the text exactly at the middle line of the thumbnail image,
in the Holiday packages section, we use flex-direction: column; to show each description below the belonging definition (Families, Students, Couples).
In the other sections, we won’t use flexbox for inline alignment, as it can be done with basic CSS rules, namely margin and width:
This is how our aligned mega menu looks the moment:
5. Remove the Template Helpers
Now, everything lines up properly! We now have to remove the template’s helper colors and borders and add the final colors to the links and heading sections. Below, you can find the final CSS without the hover rule:
The HTML is still the same as in Step 3. However, we’ve also added a down-arrow icon from Font Awesome to the Holidays menu item to indicate the presence of the mega menu (we style it using the .menu-icon handle in the CSS above).
Now, our flexbox mega menu is up and running. In the demo below, you can test it and check out the corresponding HTML and CSS code, too:
Although building a mega menu is a complicated task, it’s perfectly doable with flexbox, especially if you first create a template that helps you get the layout right.
You might ask if it’s not easier/better to create a mega menu with CSS grid instead of flexbox, and I say “it depends”. Although CSS grid allows you to create two-dimensional layouts, flexbox comes with out-of-the-box content awareness which is ideal in this scenario.
If you turn each row of the mega menu into a flex container, you can apply different alignment, wrapping, and sizing rules to each. This is the design principle that flexbox-based frameworks such as Bootstrap 4 follow, too. Besides, flexbox still has better support than CSS grid (currently 98.3% of all browsers used globally compared to CSS grid’s 92.03%, however this will change in the future).