0

I have a piece of code that splits my wp_list_pages navigation into two columns:

<div id="head">
    <ul>
        <?php
            $page_s = explode("</li>",wp_list_pages('title_li=&echo=0&depth=1'));
            $page_n = count($page_s) - 1;
            $page_col = round($page_n / 2);
            for ($i=0; $i < $page_n; $i++){
                if ($i < $page_col){
                    $left = $left.''.$page_s[$i].'</li>';
                } else if ($i>=$page_col) {
                    $right = $right.''.$page_s[$i].'</li>';
                }
            }
        ?>
        <div id="nav">
            <div>
                <?php echo $left; ?>
            </div>
            <div>
                <a href="<?php bloginfo('url'); ?>"><img src="<?php bloginfo('template_directory'); ?>/images/logo.png" alt="Logo" title="Logo" /></a>
            </div>
            <div>
                <?php echo $right; ?>
            </div>
        </div>
    </ul>
</div>

This code is working great! The problem becomes the depth parameter, when I remove it so the children of the menu show, then it comes out looking awful because the code is trying to split everything in wp_list_pages not just the parent menu items.

What I am trying to do is have the children menu items show when someone hovers over the link (dropdown), then when the page gets smaller, I'd like them to become part of the list of menu items - so people can still see them, they just won't hover because that's not possible on smaller screens.

My CSS looks like:

#nav {
      display: flex;
      text-align: center;
      width: 100%;
}

#nav div {
      align-items: center;
      display: flex;
      flex: 1;
      justify-content: center;
}

#nav div li {
      flex: 1;
      font-family: 'Lato', sans-serif;
      font-size: 15px;
      font-weight: 300;
      letter-spacing: 5px;
      text-transform: uppercase;
}

#nav div li.current_page_item a {
      font-weight: 400;
}

#nav div li.current_page_item a,
#nav div li a:hover {
      border-bottom: 1px solid #4a5f73;
}

#nav div a {
      border-bottom: 1px solid transparent;
      color: #4a5f73;
      padding: 0 5px 5px 10px;
      text-decoration: none;
}

#nav div img {
      height: auto;
      margin: 0 auto;
      max-width: 450px;
      width: 100%;
}

@media screen and (max-width: 1200px) {
    #nav {
           flex-direction: column;
    }
    #nav div li {
           padding: 20px 0;
    }
}

@media screen and (min-width: 1199px) {
    #nav div li {
           padding: 65px 0 30px;
    }
}

Fiddle: https://jsfiddle.net/uodhenyL/

Any help is appreciated.

Thanks,
Josh

0

I got everything working, but had to change my approach to get it working the way I wanted.

Basically, the easiest approach (at least for me), was to create two menus...one for small screen sizes and one for larger ones.

So, the code looks like:

<!-- Head -->
<div id="head">
    <!-- Nav -->
    <ul class="nav">
        <?php
            wp_list_pages("title_li=");
        ?>
    </ul>
    
    <!-- Small Nav -->
    <div class="sm-nav">
        <div class="overlay" id="overlay" role="navigation" aria-expanded="false">
            <button type="button" name="close" class="toggle close" id="close" aria-controls="overlay"><i class="ion-android-close"></i></button>
            <ul>
                <?php
                    wp_list_pages("title_li=");
                ?>
            </ul>
        </div>
        <button type="button" name="open" class="toggle open" id="open" aria-controls="overlay"><i class="ion-navicon"></i></button>
        <div class="logo">
            <a href="<?php bloginfo('url'); ?>"><img src="<?php bloginfo('template_directory'); ?>/images/logo.png" alt="Logo" title="Logo" /></a>
        </div>
    </div>
</div>

I had to add a small piece of jQuery to make the logo appear in the list on the larger menu:

<script>
    $(function() {
        // Nav Logo
        $('.nav li:eq(2)').after('<div class="logo"><a href="<?php bloginfo('url'); ?>"><img src="<?php bloginfo('template_directory'); ?>/images/logo.png" alt="Logo" title="Logo" /></a></div>');
    });
</script>

Then, I had to add some JavaScript to make the smaller navigation work:

/*
     Trap focus function for the overlay
     https://hiddedevries.nl/en/blog/2017-01-29-using-javascript-to-trap-focus-in-an-element
*/

 function trapFocus(element) {
     var focusableEls = element.querySelectorAll('a[href], button, textarea, input[type="text"], input[type="radio"], input[type="checkbox"], select'),
     firstFocusableEl = focusableEls[0];
     lastFocusableEl = focusableEls[focusableEls.length - 1];
     KEYCODE_TAB = 9;

     element.addEventListener('keydown', function(e) {
         var isTabPressed = (e.key === 'Tab' || e.keyCode === KEYCODE_TAB);
         if (!isTabPressed) {
             return;
        }
         if ( e.shiftKey ) /* shift + tab */ {
             if (document.activeElement === firstFocusableEl) {
                 lastFocusableEl.focus();
                 e.preventDefault();
            }
        } else /* tab */ {
             if (document.activeElement === lastFocusableEl) {
                 firstFocusableEl.focus();
                 e.preventDefault();
            }
        }
    });
}

/* 
     onclick functions to launch the overlay and toggle the required classes
*/

 document.addEventListener('DOMContentLoaded', function() {
     var overlay = document.getElementById('overlay');
     var scrollPos = document.querySelector('body').scrollTop; // [1]

     document.getElementById('open').addEventListener('click', function() {
         document.getElementById('overlay').classList.toggle('menu');
         document.querySelector('body').classList.toggle('active');
         document.getElementById('overlay').setAttribute('aria-expanded', 'true');
         document.getElementById('close').focus();
         trapFocus(overlay);
    });

     document.getElementById('close').addEventListener('click', function() {
         document.getElementById('overlay').classList.toggle('menu');
         document.querySelector('body').classList.toggle('active');
         document.getElementById('overlay').setAttribute('aria-expanded', 'false');
         document.getElementById('open').focus();
         document.querySelector('body').scrollTop = scrollPos; // [1]
    });
});

and finally...the CSS:

/* Small Nav */
@media screen and (max-width: 850px) {
    body.active {
        overflow: hidden;
    }
    .sm-nav .overlay {
        background: rgba(95, 105, 117, 0.9);
        bottom: 0;
        color: #fff;
        left: 0;
        opacity: 0;
        overflow-x: hidden;
        overflow-y: scroll;
        position: fixed;
        right: 0;
        top: 0;
        transition: opacity 0.2s, visibility 0.2s;
        visibility: hidden;
        z-index: 800;
        /* Scrolling */
        -webkit-overflow-scrolling: touch;
    }
    .sm-nav .menu {
        display: block;
        opacity: 1;
        visibility: visible;
    }
    .sm-nav button {
        background: none;
        border: 0;
        font-size: 50px;
    }
    .sm-nav .ion-navicon:before {
        color: #5f6975;
    }
    .sm-nav #overlay {
        padding-top: 60px;
        text-align: center;
    }
    .sm-nav #overlay button {
        color: #fff;
    }
    .sm-nav #overlay button:hover {
        cursor: pointer;
    }
    .sm-nav #overlay li a {
        border-bottom: 1px solid transparent;
        color: #fff;
        display: inline-block;
        font-family: 'Lato', sans-serif;
        font-size: 15px;
        font-weight: 300;
        letter-spacing: 5px;
        margin: 5px 0;
        padding: 15px 5px 5px 10px;
        text-decoration: none;
        text-transform: uppercase;
    }
    .sm-nav #overlay li.current_page_item a {
        border-bottom: 1px solid #fff;
        font-weight: 400;
    }
    .sm-nav #overlay li.current_page_item ul.children a {
        border-bottom: none;
        font-weight: 300;
    }
    .sm-nav #open,
    .sm-nav #close {
        left: 0;
        margin: auto;
        position: absolute;
        right: 0;
        top: 15px;
    }
    .sm-nav #open:hover,
    .sm-nav #close:hover {
        cursor: pointer;
    }
    body.active #open,
    .nav {
        display: none;
    }
    .sm-nav .logo {
        text-align: center;
    }
    .sm-nav .logo img {
        height: auto;
        max-width: 400px;
        transition: 0.5s;
        width: 100%;
    }
    .sm-nav .logo a:hover {
        opacity: 0.9;
    }
}

/* Nav */
@media screen and (min-width: 851px) {
    body {
        overflow-x: hidden;
    }
    .nav {
        display: flex;
        height: 80px;
        justify-content: space-around;
        margin: 0 auto 50px;
        position: relative;
    }
    .nav > * {
        align-items: center;
        flex: 1;
        display: flex;
        justify-content: center;
        text-align: center;
    }
    .nav ul,
    .sm-nav {
        display: none;
    }
    .nav li:hover > ul {
        display: block;
    }
    .nav li a {
        border-bottom: 1px solid transparent;
        color: #5f6975;
        display: block;
        font-family: 'Lato', sans-serif;
        font-size: 15px;
        font-weight: 300;
        letter-spacing: 5px;
        padding: 15px 5px 5px 10px;
        text-decoration: none;
        text-transform: uppercase;
    }
    .nav ul.children li a,
    .nav ul.children li:hover a {
        color: #fff;
        margin: 0 30px;
    }
    .nav ul.children li:hover {
        background: #4c545d;
    }
    .nav li a:hover,
    .nav li:hover > a {
        border-bottom: 1px solid #4a5f73;
    }
    .nav li.current_page_ancestor a {
        border-bottom: 1px solid #4a5f73;
        font-weight: 400;
    }
    .nav li:hover > ul.children a,
    .nav li.current_page_ancestor ul.children a {
        border-bottom: none;
        font-weight: 300;
    }
    .nav li.current_page_item a {
        border-bottom: 1px solid #4a5f73;
        font-weight: 400;
    }
    .nav ul {
        background: #5f6975;
        position: absolute;
        top: 100%;
    }
    .nav ul li {
        border-top: 1px solid #4c545d;
        position: relative;
    }
    .nav ul li a {
        padding: 15px 10px;
    }
    .nav ul ul {
        left: 100%;
        position: absolute;
        top: 0;
    }
    .nav .logo {
        flex: 0 0 20%;  
    }
    .nav .logo img {
        height: auto;
        max-width: 400px;
        transition: 0.5s;
        width: 100%;
    }
    .nav .logo a:hover {
        opacity: 0.9;
    }
}

I am using media queries to display one navigation bar at a time...I hide the larger nav, while displaying the smaller nav and vice-versa. That way the user only sees one of them at a time, but I can style and use them appropriately.

Also, I have the classes surrounding both menus: nav and sm-nav, that way I can have two of the same classes in the menus, but I can style and use them differently - one won't affect the other.

I know I have used simpler code in the past to do this, but this is what I found that would work. Please feel free to make any recommendations. This code has been copied and pasted from several sources and I'm sure could be written or implemented much better than I have done.

Hope this helps someone.

Thanks,
Josh

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.