Skip to content

Instantly share code, notes, and snippets.

@ahaywood
Last active September 29, 2021 18:33
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save ahaywood/ae3c33ea20f91d8f13e51269a22cb0b1 to your computer and use it in GitHub Desktop.
Save ahaywood/ae3c33ea20f91d8f13e51269a22cb0b1 to your computer and use it in GitHub Desktop.
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
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
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.

@sophiawzey
Copy link

sophiawzey commented Mar 3, 2020

Thank you Amy for saving me a ton of time!!

In case anyone else is looking for a third level, I forked this gist to add the third level (I didnt need home / search)

https://gist.github.com/sophiawzey/d94238e510ff26f9db4006164adaed73

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment