Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
WordPress: Mega Menu
/*------------------------------------*\
#PRIMARY-MENU
\*------------------------------------*/
.primary-menu {
@include grid;
@include sans-serif;
font-weight: $bold;
height: $nav-bar-height;
&__wrapper {
@include clearfix();
background: rgba(white, 0.3);
}
/* more explicit here to prevent conflicts with
the megamenu / subnav */
> .nav > ul {
@include no-margin-padding();
@include no-bullets();
display: flex;
flex-direction: row;
justify-content: space-between;
> li {
border-top: 2px solid transparent;
&:hover {
background: white;
border-top: 2px solid $dark-slate-blue;
/* show mega menu on rollover */
.mega-menu__wrapper {
display: block;
}
}
> a {
box-sizing: border-box;
color: $dark-slate-blue;
display: block;
letter-spacing: 1px;
line-height: 40px;
padding: 10px 35px;
text-decoration: none;
text-transform: uppercase;
}
}
}
.sub-menu {
display: none;
}
}
/* home */
.nav-home a {
@include remove-text;
background: path('icon-home.svg') center center no-repeat;
&:hover {
background: white path('icon-home.svg') center center no-repeat;
}
}
/* search - needs to be specific in order to prevent
interferences with the search bar */
.nav-search > a {
@include remove-text;
background: path('icon-search.svg') center center no-repeat;
left: 0;
position: relative;
transition: left 0.5s ease-in-out;
&:hover {
background: white path('icon-search.svg') center center no-repeat;
}
}
/*------------------------------------*\
#MEGA-MENU
\*------------------------------------*/
@keyframes reveal-mega-menu {
0% {
height: 0%;
}
100% {
height: auto;
}
}
@keyframes fadein-mega-menu {
0% {
opacity: 0;
top: -5px;
}
100% {
opacity: 1;
top: 0;
}
}
.mega-menu {
@include grid;
animation: fadein-mega-menu .5s ease-in-out;
position: relative;
&__wrapper {
animation: reveal-mega-menu .25s ease-in-out;
background: white;
box-shadow: 0 4px 4px -2px #777;
display: none;
left: 0;
min-height: 320px;
padding: 35px 0 45px;
position: absolute;
width: 100%;
z-index: map-get($zindex, mega-menu);
}
/* content within the mega menu */
&__content {
@include push(1);
@include span(7);
box-sizing: border-box;
border-right: 10px solid $butterscotch;
padding-left: 33px;
padding-right: 120px;
/* mega menu title */
h2 {
@include sans-serif($light);
font-size: em(28px);
color: $dark-slate-blue;
letter-spacing: 1px;
margin-bottom: 10px;
margin-top: 25px;
}
/* description */
p {
@include serif;
font-size: em(18px);
font-weight: normal;
line-height: em(28px, 18px);
margin-bottom: 30px;
}
/* learn more button */
.learn-more {
@include btn--inverse($dark-slate-blue, $dark-slate-blue, white);
margin-bottom: 25px;
&:after {
@include btn-arrow($dark-slate-blue);
}
&:hover:after {
@include btn-arrow(white);
}
}
}
/* subnavigation within the mega menu */
&__subnav {
@include span(4);
@include last;
.subnav {
@include no-bullets;
padding: 0;
margin: 25px 0 25px 40px;
li {
font-size: em(16px);
line-height: em(20px, 16px);
margin-bottom: 20px;
a {
color: $dark-slate-blue;
text-decoration: none;
text-transform: uppercase;
&:hover {
color: $butterscotch;
}
}
}
}
}
}

I've written a massive blog post explaining this code.

A few things that are included in this gist, that might not be immediately obvious and will prevent this code from being a simple copy and paste

Within the .scss,

  • There are a few references to the Susy grid.
  • I've also referenced a few of my Sass go to mixins and extends. I've written a post about these, too.
  • There are a few references to color variables, I reference in a separate _theme.scss file.

Within WordPress

There's quite a bit of setup required in WordPress, in order for this code to work. Again, this is explained within the blog post.

<!-- NAV BAR -->
<div class="primary-menu__wrapper">
<div class="primary-menu">
<nav class="nav" role="navigation">
<ul>
<?php $locations = get_nav_menu_locations();
// if there's a location for the primary menu
if ( isset( $locations['primary-menu']) ) {
$menu = get_term( $locations['primary-menu'], 'nav_menu');
// if there are items in the primary menu
if ( $items = wp_get_nav_menu_items( $menu->name ) ) {
// loop through all menu items to display their content
foreach ( $items as $item ) {
// if the current item is not a top level item, skip it
if ($item->menu_item_parent != 0) {
continue;
}
// get the ID of the current nav item
$curNavItemID = $item->ID;
// get the custom classes for the item
// (determined within the WordPress Appearance > Menu section)
$classList = implode(" ", $item->classes);
echo "<li class=\"{$classList}\">";
echo "<a href=\"{$item->url}\">{$item->title}</a>";
// build the mega-menu
// if 'mega-menu' exists within the class
if ( in_array('has-mega-menu', $item->classes)) { ?>
<div class="mega-menu__wrapper js-mega-menu">
<div class="mega-menu">
<div class="mega-menu__content">
<h2><?= $item->post_title; ?></h2>
<p><?= $item->description; ?></p>
<a href="<?= $item->url; ?>" class="learn-more">Learn More</a>
</div>
<div class="mega-menu__subnav">
<nav>
<ul class="subnav">
<?php // cycle through the menu items and get the subnav
foreach ( $items as $subnav) {
if ( $subnav->menu_item_parent == $curNavItemID) {
echo "<li><a href=\"{$subnav->url}\">{$subnav->title}</a>";
}
} ?>
</ul>
</nav>
</div>
</div>
</div>
<?php }
// if this is the search bar
if ( in_array('nav-search', $item->classes) ) { ?>
<div class="search-bar__wrapper">
<div class="search-bar">
<div class="search-bar__form">
<form>
<input type="text" name="s" placeholder="Keywords" />
<button type="button" role="submit" name="Search">Search</button>
</form>
<a href="#" class="js-close-search search-bar__close"><svg role="img" class="icon"><use xlink:href="<?php bloginfo('template_url'); ?>/assets/dist/img/svg.svg#close"></use></svg></a>
</div> <!-- /.search-bar__form -->
</div><!-- /.search-bar -->
</div><!-- /.search-bar__wrapper -->
<?php }
echo '</li>';
}
}
} ?>
</ul>
<?php //nationsu_primary_nav(); ?>
</nav>
</div><!-- /.primary-menu -->
</div> <!-- /.primary-menu__wrapper -->
@dgpope

This comment has been minimized.

Copy link

dgpope commented Aug 22, 2019

I know this is kind of old but I had a random question if you had any idea how to bring in a 3rd level if the subnav has children.

@dgpope

This comment has been minimized.

Copy link

dgpope commented Aug 23, 2019

// if 'mega-menu' exists within the class
if ( in_array('is-mega-menu', $item->classes)) {
?>


                                    <div class="mega-menu__content">
                                        <h2><?= $item->post_title; ?></h2>
                                        <p><?= $item->description; ?></p>
                                        <a href="<?= $item->url; ?>" class="learn-more">Learn More</a>
                                    </div>
											<?php 
											
											$second_level = '';
											$third_level = '';
                                            foreach ( $items as $subnav) {
												$subnav_ID = $subnav->menu_item_parent;
                                                if ( $subnav_ID == $curNavItemID) {
                                                    $second_level .= "<li><a href=\"{$subnav->url}\" id=\"{$subnav->object_id}\">{$subnav->title} {$subnav->children}</a></li>";
                                                }
											
												if ( in_array('has-submenu', $subnav->classes)) {
													
													$third_level = wp_list_pages( array(
														// Only pages that are children of the current page
														'child_of' => $subnav_ID,
														// Only show one level of hierarchy
														'depth' => 1
													) );
												}
												
												
											} 
												?>
												<div class="mega-menu__subnav">
                                        <nav>
                                            <ul class="subnav">
                                            <?php echo $second_level;

unset($second_level); ?>


												<div class="mega-menu__subnav_level_2">
                                        <nav>
                                            <ul class="subnav">
											<?php echo $third_level;

unset($third_level); ?>


                                </div>
                            </div>
                        <?php }

This is what I am trying but I cannot get it to work correctly to display the third level. If you have any idea on a different way or something I am missing it would be greatly appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.