CSS Flexbox #15. How to Create a Megamenu With Flexbox
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.
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
- CSS Flexbox #1. Creating Your First Flexbox Layout
- CSS Flexbox #2. How to Use the justify-content Property
- CSS Flexbox #3. The align-items Property
- CSS Flexbox #4. The flex-grow Property
- CSS Flexbox #5. The flex-shrink Property
- CSS Flexbox #6. The flex-basis Property
- CSS Flexbox #7. The order Property
- CSS Flexbox #8. The flex-wrap Property
- CSS Flexbox #9. The align-content Property
- CSS Flexbox #10. The flex Shorthand Property
- CSS Flexbox #11. Shorthand Default Values
- CSS Flexbox #12. The flex-flow shorthand property
- CSS Flexbox #13. Create a Navigation Menu with Flexbox
- CSS Flexbox #14. How to Build a Card Layout in Flexbox