Search code examples
jqueryaccordionslidedown

choppy animation on jquery accordion menu submenu


I have a vertical accordion menu with one submenu. When the option with the submenu is clicked the submenu opens but there's a clunkiness to it. Here's a jsfiddle of the code. I would like the opening and closing to be smooth but I can't for the life of me figure out how to achieve this.

https://jsfiddle.net/rhinorck/vhqynbep/

 <!-- Menu -->
    <section>
        <div class="home-menu text-center">
            <nav class="navigation">
                <ul class="mainmenu">
                    <li class="dropdown"> <a href="#" class="dropdown-li">Shop</a>
                        <ul class="submenu">
                            <li><a href="monmouth.html">Monmouth</a></li>
                            <li><a href="shopify.html">Online</a></li>
                        </ul>
                    </li>
                    <li><a href="ethos.html">Ethos</a></li>
                    <li><a href="contact.html">Contact</a></li>
                </ul>
            </nav>
        </div>
    </section>
    <!-- End Menu -->

**CSS**

.mainmenu,
.submenu,
.sidemenu-nav {
list-style: none;
padding: 0;
margin: 0;
}

ul.mainmenu a {
font-family: 'Homemade Apple', cursive;
position: relative;
display: block;
text-decoration: none;
padding: 25px 20px;
margin: 10px auto;
text-transform: capitalize;
color: rgba(76, 76, 76, 1.0);
font-size: 2.35em;
}

ul.mainmenu li:nth-child(odd) {
background: url("../img/menu_item_bg.svg") no-repeat;
background-position: center center;
background-size: contain;
}

ul.mainmenu li:nth-child(1) {
background: none;
}

.dropdown-li {
background: url("../img/menu_item_alt_bg.svg") no-repeat;
background-position: center center;
background-size: contain;
}

ul.mainmenu li:nth-child(even) {
background: url("../img/menu_item_alt_2_bg.svg") no-repeat;
background-position: center center;
background-size: contain;
}
ul.submenu a {
font-family: 'Homemade Apple', cursive;
margin: 10px auto;
text-transform: capitalize;
color: rgba(76, 76, 76, 1.0);
font-size: 1.35em;
}

ul.submenu li:nth-child(even) {
background: url("../img/menu_item_alt_2_bg.svg") no-repeat;
background-position: center center;
background-size: contain;
}

ul.submenu li:nth-child(odd) {
background: url("../img/menu_item_alt_bg.svg") no-repeat;
background-position: center center;
background-size: contain;
}

**JQuery**
$(".mainmenu > ul").ready(function () {
    $("ul.submenu").attr('style', 'display:none;');
});
$(".mainmenu > li > a").on("click", function (e) {
    //if submenu is hidden, does not have active class  
    if (!$(this).hasClass("active")) {
        // hide any open menus and remove active classes
        $(".mainmenu li ul").slideUp(350);
        $(".mainmenu li a").removeClass("active");
        // open submenu and add the active class
        $(this).next("ul").slideDown(350);
        $(this).addClass("active");
        //if submenu is visible    
    }
    else if ($(this).hasClass("active")) {
        //hide submenu and remove active class
        $(this).removeClass("active");
        $(this).next("ul").slideUp(350);
    }
});

Solution

  • The "choppy" issue is coming from margin: 10px auto; on ul.mainmenu a. Remember, that selector is targeting EVERY a element contained within .mainmenu. So when you click your .dropdown-li, the slide animation plays and the 10px margin between two li elements becomes 20 between the ul.mainmenu and ul.submenu; at least until the animation has completed which is what is causing the jump.

    There is a quick and easy built in jQuery function for this exact thing your trying to create:

    $(document).ready(function() {
      $('.dropdown-li').click(function() {
        $('.submenu').toggle('fast')
      });
    });
    .mainmenu,
    .submenu,
    .sidemenu-nav {
      list-style: none;
      padding: 0;
      margin: 0;
    }
    ul.mainmenu a {
      font-family: 'Homemade Apple', cursive;
      position: relative;
      display: block;
      text-decoration: none;
      padding: 25px 20px;
      text-transform: capitalize;
      color: rgba(76, 76, 76, 1.0);
      font-size: 2.35em;
    }
    ul.mainmenu li:nth-child(odd) {
      background: url("../img/menu_item_bg.svg") no-repeat;
      background-position: center center;
      background-size: contain;
    }
    ul.mainmenu li:nth-child(1) {
      background: none;
    }
    .dropdown-li {
      background: url("../img/menu_item_alt_bg.svg") no-repeat;
      background-position: center center;
      background-size: contain;
    }
    ul.mainmenu li:nth-child(even) {
      background: url("../img/menu_item_alt_2_bg.svg") no-repeat;
      background-position: center center;
      background-size: contain;
    }
    ul.submenu a {
      font-family: 'Homemade Apple', cursive;
      margin: 10px auto;
      text-transform: capitalize;
      color: rgba(76, 76, 76, 1.0);
      font-size: 1.35em;
    }
    ul.submenu li:nth-child(even) {
      background: url("../img/menu_item_alt_2_bg.svg") no-repeat;
      background-position: center center;
      background-size: contain;
    }
    ul.submenu li:nth-child(odd) {
      background: url("../img/menu_item_alt_bg.svg") no-repeat;
      background-position: center center;
      background-size: contain;
    }
    ul.submenu {
      display: none;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <!-- Menu -->
    <section>
      <div class="home-menu text-center">
        <nav class="navigation">
          <ul class="mainmenu">
            <li class="dropdown"> <a href="#" class="dropdown-li">Shop</a>
              <ul class="submenu">
                <li><a href="monmouth.html">Monmouth</a>
                </li>
                <li><a href="shopify.html">Online</a>
                </li>
              </ul>
            </li>
            <li><a href="ethos.html">Ethos</a>
            </li>
            <li><a href="contact.html">Contact</a>
            </li>
          </ul>
        </nav>
      </div>
    </section>
    <!-- End Menu -->

    I removed the margin property from your top-most a element as it is causing the "choppiness" I added a property to your .submenu. display: none will hide the submenu on page-load. In the Javascript, the jQuery function .toggle will toggle between two other jQuery functions. Those functions are .show() and .hide(). This is essentially adding the display: none property for .hide() and display: block property for .show().

    I hope this helps!