CSS Flexbox #15. How to Create a Megamenu With Flexbox

| Web Design

How to Create a Flexbox Megamenu for a Newspaper

If you have a busy website, you often have a busy menu.

That is why the navigation menus on these sites gradually start to look like user interfaces instead of simple menus. These menus with many features are often called megamenus.

In this tutorial, I will explain how to build a user-friendly mega menu using CSS Flexbox. I'll take you through 6 steps to create this menu.

Step #1. The HTML

  • Open the code editor of your liking
  • Create an empty HTML file
  • Visit this page, copy the HTML code and save the file.

CSS Flexbox #15. How to Create a Megamenu With Flexbox

The whole menu is a collection of lists and nested lists.

There are links to Google Fonts and FontAwesome in the <header> section of the html file. There are 2 script calls at the end of the file, right after the closing </body> tag. There is also a link to a stylesheet file called style.css


Step #2. The Basic CSS Reset

  • Create a file called style.css
  • Add this code to the file:
html {
box-sizing: border-box;
font-size: 16px;
}
*  , *:before, *:after {
box-sizing: inherit;
}

body, h1, h2, h3, h4, h5, h6, p, ol, ul {
margin: 0;
padding: 0;
font-weight: normal;
}

ol, ul {
list-style: none;
}

Step #3. The Layout

The approach I took to better understand this exercise, was to separate the layout in sections and analyze how many flex-containers would pass in each section.

The .main-menu-container element is a flex container and so are its direct descendants:

  • .main-menu
  • .resources
  • .login-block

  • Edit the CSS code:
.main-menu-container.
.main-menu.
.resources.
.login-block {
display: flex;
}

The layout shows that the first child item takes more space within the container than its siblings. Let’s change the proportion in which they grow relative to each other (flex-grow).

  • Edit the CSS code:
.main-menu {
flex-grow: 3;
}

.resources {
flex-grow: 2;
}

.login-block {
flex-grow: 1;
}

The .highlights section is a flex container with four children, three of them are likewise flex containers.

  • .highlights
  • .topics
  • .social-wrapper

Notice that the .social-wrapper container has two more flex containers in it.

  • .social
  • .search
  • Edit the CSS code:
/* Highlights section */

.highlights.
.topics.
.social.
.search.
.social-wrapper {
display: flex;
}

Now distribute the space between all flex items using the flex-basis property. The first <li> item inside the .topics container is narrower than its siblings.

  • Edit the CSS code:
.logo {
flex-basis: 25%;
}

.topics {
flex-basis: 60%;
}

.topics li {
flex-basis: 22.5%;
}

.topics li:first-of-type {
flex-basis: 10%;
}

.social-wrapper {
flex-basis: 15%;
}

The .social-wrapper flex container has its flex-direction property set to column. The items are vertically centered and placed at the bottom of the flex container.

  • Edit the CSS code:
.social-wrapper {
flex-basis: 15%;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}

The last part of the layout is the .news-menu container. It has multiple .news-categories, each one of these categories is a flex container too.

The .megamenu-local section is a flex-container with two other flex containers inside it:

  • .main-topics-list
  • .main-news

  • Edit the CSS code:
.news-menu.
.news-categories.
.megamenu-local.
.main-news {
display: flex;
}

The news links are centered within their container.

  • Edit the CSS code:
.news-menu {
justify-content: center;
}

The space is distributed within the megamenu in 3 columns (25/50/25). Items are centered vertically.

  • Edit the CSS code:
.megamenu-local {
align-items: center;
}

.megamenu-local > li:nth-of-type(odd) {
flex-basis: 25%;
}

.megamenu-local > li:nth-of-type(even) {
flex-basis: 50%;
}

The first and third columns are oriented to the block axis (flex-direction: column).

  • Edit the CSS code:
.main-topics-list.
.main-news {
flex-direction: column;
align-items: center;
}

These are all the flexbox styles that we need for this layout.


Step #4. The Other Styles

Change the background color of .main-menu-container and insert a background image to the header container.

  • Edit The CSS code:
.main-menu-container {
background-color: black;
}

.header-container {
background-image: url(http://lorempixel.com/640/300/abstract/6);
background-repeat: repeat-x;
}

Links and images.

  • Edit the CSS code:
a {
display: block;
text-decoration: none;
text-transform: uppercase;
padding: 0.5em 0.5em;
color: whitesmoke;
font-family: 'Roboto Condensed', sans-serif;
font-weight: normal;
}

img {
display: block;
max-width: 100%;
height: auto;
}

Styling the .login-block

  • Edit the CSS code:
/* Login block links */

.login-block li a {
border: 1px solid whitesmoke;
border-radius: 3px;
background-color: #868282;
padding: 0 0.8em;
margin-top: 0.5em;
}
.login-block li a:hover {
 background-color: rgb(250, 224, 77);
 color: black;
}
.login-block li:first-of-type {
 margin-right: 0.5em;
}

Center the logo image. The topics title is bolder than its siblings.

  • Edit the CSS code:
.topics li:first-of-type a {
font-weight: 700;
letter-spacing: 3px;
}

.logo img {
margin: 0 auto;
}

Other cosmetic styling.

  • Edit the CSS code:
/* Other borders and margins */

.social i {
font-size: 1.8em;
}

.search {
padding: 1em;
}

.search-box {
background-color: transparent;
line-height: 1.5em;
color: whitesmoke;
}

.fa-search {
color: whitesmoke;
position: relative;
right: 2em;
top: 0.3em;
}

.highlights {
margin-top: 2em;
}

.topics li {
border: 1px solid whitesmoke;
border-top: none;
}

.topics li:first-of-type {
border-left: none;
}

.social li {
border-right: 1px solid whitesmoke;
padding: 0 1em;
}

.social li:last-of-type {
border-right: none;
}

.news-categories {
padding-top: 1.5em;
}

.news-categories > li > a {
font-size: 1.1em;
font-weight: 700;
}

li.local {
border-top: 5px solid #9c1f42;
}

li.national {
border-top: 5px solid #e13249;
}

li.international {
border-top: 5px solid #db5c72;
}

li.business {
border-top: 5px solid #96B45C;
}

li.sports {
border-top: 5px solid #006638;
}

li.opinion {
border-top: 5px solid #FF9E37;
}

li.culture {
border-top: 5px solid #6C2869;
}

li.tendencies {
border-top: 5px solid #332265;
}

li.technology {
border-top: 5px solid #195EB5;
}

li.entertainment {
border-top: 5px solid #58C5E0;
}

li.local > a:hover {
background-color: #9c1f42;
}

li.national > a:hover {
background-color: #e13249;
}

li.international > a:hover {
background-color: #db5c72;
}

li.business > a:hover {
background-color: #96B45C;
}

li.sports > a:hover {
background-color: #006638;
}

li.opinion > a:hover {
background-color: #FF9E37;
}

li.culture > a:hover {
background-color: #6C2869;
}

li.tendencies > a:hover {
background-color: #332265;
}

li.technology > a:hover {
background-color: #195EB5;
}

li.entertainment > a:hover {
background-color: #58C5E0;
}

You need to add one last “layout” positioning style to make the mega menu fit.

  • Edit the CSS code and place this snippet before the flexbox styles:
.wrapper {
position: relative;
width: 80%;
margin: 0 auto;
}
.megamenu-local {
position: absolute;
background-color: rgb(228, 228, 228);
margin: 0 auto;
left: 0;
padding-bottom: 1em;
}

Add some more styling.

  • Edit the CSS code:
.megamenu-local a {
color: #838383;
}

.main-news {
width: 95%;
}

.main-news li {
border-bottom: 2px inset #838383;
line-height: 1.8em;
text-align: center;
}

.main-news li:last-of-type {
border-bottom: none;
}

Step #5. Hide the Mega Menu

Create one last class called .hidden-megamenu-local and replace it in the HTML code for the .megamenu-local class.

  • Edit the HTML code:

  • Edit the CSS code:
.hidden-megamenu-local {
display: none;
}

Hint: Make sure you place this code before all flexbox styles.


Step #6. The JavaScript Code

  • Create a file called script.js. The links to the file and to jQuery are already in the HTML file.
  • Copy and paste this code:
$('li.local').hover(
 function(){ $('.hidden-megamenu-local').addClass('megamenu-local') }.
 function(){ $('.hidden-megamenu-local').removeClass('megamenu-local') }
)

$('.megamenu-local').hover(
 function(){ $('.hidden-megamenu-local').addClass('megamenu-local') }.
 function(){ $('.hidden-megamenu-local').removeClass('megamenu-local') }
)

What does the first part of this Javascript code do? When hovering over the list item, the class megamenu-local will be added to the HTML and the mega menu will be displayed, the mega menu will disappear when the cursor leaves the list item.

Second part:

What does the second part of this code do? When hovering over the mega menu, the class megamenu-local will be added to the HTML and the mega menu will still be displayed, the mega menu will disappear when the cursor leaves it.

I hope this tutorial has helped you practice basic and advanced Flexbox concepts as well. Thanks for reading!


Previous tutorials in this Flexbox series


About the author

Jorge lived in Ecuador and Germany. Now he is back to his homeland Colombia. He spends his time translating from English and German to Spanish. He enjoys playing with Drupal and other Open Source Content Management Systems and technologies.