Wrote an animation of the drop-down menu list with hover on its parent.

There is one significant problem in the general 'construction' - hover over the parent several times in a row and you will see that the drop-down list is not always shown. While his first function + animation doesn’t work to the end, the second one will not start.

Question: how to optimize the code so that it responds by 'dropping out' the list for each hover parent?

$(function() { $.fn.extend({ animateCss: function(animationName, callback) { var animationEnd = (function(el) { var animations = { animation: 'animationend', OAnimation: 'oAnimationEnd', MozAnimation: 'mozAnimationEnd', WebkitAnimation: 'webkitAnimationEnd', }; for (var t in animations) { if (el.style[t] !== undefined) { return animations[t]; } } })(document.createElement('div')); this.addClass('animated ' + animationName).one(animationEnd, function() { $(this).removeClass('animated ' + animationName); if (typeof callback === 'function') callback(); }); return this; }, }); $('#yourElement').animateCss('bounce', function() { }); $('.nav__item.dropdown').hover( function(){ var dropdown = $(this).find('>.nav'); dropdown.removeClass('hide'); dropdown.addClass('show'); $(dropdown).animateCss('fadeInUp'); }, function(){ var dropdown = $(this).find('>.nav'); $(dropdown).animateCss('fadeOutDown', function() { dropdown.removeClass('show'); dropdown.addClass('hide'); }); } ) }); 
 .show { display: block; } .hide { display: none; } .test ul { list-style-type: none; margin-top: initial; margin-bottom: initial; margin-left: initial; margin-right: initial; -webkit-padding-start: initial; } .test .nav.parents { display: flex; flex-direction: row; } .test .nav.parents > .nav__item { padding: 10px; background: salmon; } .test .nav.parents > .nav__item.dropdown > .nav { list-style-type: none; margin-top: initial; margin-bottom: initial; margin-left: initial; margin-right: initial; -webkit-padding-start: initial; position: absolute; } .test .nav.parents > .nav__item.dropdown > .nav > .nav__item { padding: 5px; background: rosybrown; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css"> <div class="test"> <ul class="nav parents"> <li class="nav__item">Parent 1</li> <li class="nav__item dropdown"> Parent 2 <ul class="nav hide"> <li class="nav__item">Child 1</li> <li class="nav__item">Child 2</li> <li class="nav__item">Child 3</li> <li class="nav__item">Child 4</li> <li class="nav__item">Child 5</li> </ul> </li> <li class="nav__item">Parent 3</li> <li class="nav__item dropdown"> Parent 4 <ul class="nav hide"> <li class="nav__item">Child 1</li> <li class="nav__item">Child 2</li> <li class="nav__item">Child 3</li> <li class="nav__item">Child 4</li> <li class="nav__item">Child 5</li> </ul> </li> <li class="nav__item">Parent 5</li> </ul> </div> 

    1 answer 1

    It is not clear why jQuery is needed, this is completely done without js at all

     * { list-style: none; text-decoration: none; margin: 0; padding: 0; } ul { display: flex; flex-direction: row; width: 100%; justify-content: space-around; background: #fbfbfb; } ul li ul { display: flex; flex-direction: column; transform: translate(0, 100px)scale(1.2); visibility:hidden; opacity: 0; transition: .5s .4s; position: absolute; left: -5px; text-align: center; padding: 0 10px 0 0; } ul li ul li { white-space: nowrap; } li { padding: 10px 20px; position: relative; } ul li:hover ul { transform: translate(0, 20px)scale(1); opacity: 1; visibility:visible; } a { font-variant: small-caps; color: blue; } .content { padding-top: 50px; } .drop:after { content: "+"; font-size: 16px; } .drop:hover:after { content: "-"; } 
     <ul> <li><a href="">item1</a></li> <li class="drop"><a href="">item2</a> <ul> <li><a href="">item2-1</a></li> <li><a href="">item2-2</a></li> <li><a href="">item2-3</a></li> <li><a href="">item2-4</a></li> <li><a href="">item2-5</a></li> </ul> </li> <li><a href="">item3</a></li> <li class="drop"><a href="">item4</a> <ul> <li><a href="">item4-1</a></li> <li><a href="">item4-2</a></li> <li><a href="">item4-3</a></li> <li><a href="">item4-4</a></li> <li><a href="">item4-5</a></li> </ul> </li> <li><a href="">item5</a></li> </ul> <div class="content"> <p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Necessitatibus animi debitis ea dolore suscipit dolor minus nesciunt eum distinctio voluptates ex dicta perspiciatis placeat culpa sit aut, beatae quae earum?</p> </div> 

    • The library is used animate.css , JS is needed so that you can hang up a certain animation element on the event ... - Mike_Ro
    • By the way, in your example, the drop-down list can be called without pointing the cursor at its parent ... - Mike_Ro
    • In your example, you can interact with the drop-down list even when it is supposedly inactive. Hover over 100px below the parent and the list will appear. - Mike_Ro
    • Yes, visibility helped out :) "here 90% of the animations on css3 are done" - all 100%. Simply, there is a library and I wanted to use it without making changes to its / her use. But for now, in truth, I am inclined to think that it is easier to register animation styles for the element itself in css without using js ... - Mike_Ro
    • There is an Animate.css library, when pointing to the parent js, the animation class clings to the drop-down list and a list with the desired animation appears (and is removed). But in js there is a problem, until the first animation (appearance) works to the end, the second animation (hide) does not start, even if we have already moved the cursor away from the parent. - Mike_Ro