Search code examples
cssnavigationpositiondropdownsubmenu

Adding Submenu to Existing Nav


I've been working on a navigation bar. I've got it styled the way I like, but for some reason am having issues getting submenus to work.

The code looks like:

<div id="head">
    <input id="toggle" type="checkbox">

    <label for="toggle" class="icon">
        <div><!-- --></div>
        <div><!-- --></div>
        <div><!-- --></div>
    </label>

    <div id="nav">
        <div>
            <ul>
                 <li class="page_item page-item-8"><a href="http://url.com/home/">Home</a></li>
                 <li class="page_item page-item-10 page_item_has_children"><a href="http://url.com/about/">About</a>
                 <ul class="children">
                     <li class="page_item page-item-22 page_item_has_children"><a href="http://url.com/about/once-more/">Once More</a>
                         <ul class="children">
                             <li class="page_item page-item-23 page_item_has_children"><a href="http://url.com/about/once-more/another-sub-page/">Another Sub Page</a>
                                 <ul class="children">
                                     <li class="page_item page-item-25"><a href="http://url.com/about/once-more/another-sub-page/final-link/">Final Link</a></li>
                                     <li class="page_item page-item-24"><a href="http://url.com/about/once-more/another-sub-page/something-else/">Something Else</a></li>
                                 </ul>
                             </li>
                         </ul>
                     </li>
                     <li class="page_item page-item-21"><a href="http://url.com/about/another-page/">Another Page</a></li>
                     <li class="page_item page-item-20"><a href="http://url.com/about/subpage/">Subpage</a></li>
                 </ul>
                 </li>
                 <li class="page_item page-item-13 current_page_item"><a href="http://url.com/shop/" aria-current="page">Shop</a></li>
                 <li class="page_item page-item-9"><a href="http://url.com/faq/">FAQ</a></li>
                 <li class="page_item page-item-11"><a href="http://url.com/contact/">Contact</a></li>
            </ul>
        </div>
    </div>
</div>

The CSS looks like:

/* Toggle */
#toggle {
    display: none;
}

/* Nav */
#nav li.current_page_item a {
    background: #d2b48c;
    border-radius: 40px;
    color: #260f03;
}

#nav li a {
    border-bottom: 1px solid transparent;
    border-top: 1px solid transparent;
    color: #fff;
    display: inline-block;
    font-family: 'Lato', sans-serif;
    font-size: 14px;
    letter-spacing: 4px;
    margin: 20px;
    padding: 10px 10px 10px 15px;
    text-decoration: none;
    text-transform: uppercase;
}

/* Media */
@media screen and (max-width: 600px) {
    /* Icon */
    .icon {
        background: #260f03;
        margin: 0 auto;
        padding: 20px 20px 30px;
        position: absolute;
        width: 100%;
        z-index: 500;
    }
    .icon div {
        background: #d2b48c;
        border-radius: 3px;
        height: 2px;
        margin: 10px auto 0;
        position: relative;
        transition: all 0.3s ease-in-out;
        width: 3em;
    }
    /* Toggle */
    #toggle:checked + .icon div:nth-child(1) {
        margin-top: 25px;
        transform: rotate(-45deg);
    }
    #toggle:checked + .icon div:nth-child(2) {
        margin-top: -2px;
        transform: rotate(45deg);
    }
    #toggle:checked + .icon div:nth-child(3) {
        opacity: 0;
        transform: rotate(45deg);
    }
    #toggle:checked + .icon + #nav {
        top: 0;
        transform: scale(1);
    }
    /* Nav */
    #nav {
        background: rgba(38, 15, 3, 0.95);
        bottom: 0;
        height: 100%;
        left: 0;
        overflow: hidden;
        position: fixed;
        right: 0;
        top: -100%;
        transform: scale(0);
        transition: all 0.3s ease-in-out;
        z-index: 200;
    }
    #nav div {
        height: 100%;
        overflow: hidden;
        overflow-y: auto;
        position: relative;
    }
    #nav ul {
        padding-top: 90px;
        text-align: center;
    }
    #nav li a:before {
        background: #fff;
        content: '';
        height: 0;
        left: -0.5em;
        position: absolute;
        transition: all 0.2s ease-in-out;
        width: 0.25em;
    }
    #nav li a:hover:before {
        height: 100%;
    }
}

@media screen and (min-width: 601px) {
    /* HIDE the dropdown */
    #nav li ul { display: none; }

    /* DISPLAY the dropdown */
    #nav li:hover > ul {
        display: block;
        position: absolute;
    }

    /* Nav */
    #nav ul {
        background: #260f03;
        font-size: 0;
        text-align: center;
    }
    #nav li {
        display: inline;
    }
    #nav li a:hover {
        border-bottom: 1px solid #d2b48c;
        border-top: 1px solid #d2b48c;
    }
}

JS Fiddle (with submenus):https://jsfiddle.net/2v8zhL3e/1/
JS Fiddle (without submenus): https://jsfiddle.net/b0mj7gp4/

I've found a bunch of tutorials on how to do this, but they are all using a float on the li.

I did have a go at it...

I hid the dropdown: #nav li ul { display: none; }

Then I showed it on hover:

#nav li:hover > ul {
    display: block;
    position: absolute;
}

Which kind of works...but the links show to the left of the main navigation item, I'd like to just tweak this so the links are stacked and show centered under their corresponding header.

I feel like I'm close, can anyone point me in the right direction?

Thanks,
Josh


Solution

  • You can add display: flex to the li:hover ul, then make the flex-direction: column and make the non-hover event position: absolute, left: 0. This creates an issue with the ul child element floating to the far left. So to fix this issue, you need to style its parent to have a relative position. The following should do the trick.

    #nav li {
      position: relative;
    }
    
    #nav li ul {  
      left: 0;
      position: absolute;
    }
    
    #nav li:hover > ul {
      display: flex;
      flex-direction: column;
    }