Dropdown animated with jQuery

2

I'm developing a website, and in its header it should contain a Dropdown that appears when giving a hover in the header link, preferably with the animation of it popping up, however it has a bug that when you go to the dropdown it tries to hide, and then appears again. With pure CSS I managed to do it without the slide animation, but I would like to give a stylized one in it, I already tried with the pure CSS with transition and the animations of @webkit.

Here is the code below:

HTML:

<li id="showDropdown" <?=$page=='areas.php' ? 'class="active"' : '';?>>
                <a class="areas" href="Javascript:void(0);">ÁREAS DE ATUAÇÃO</a>
                <ul class="dropdown-areas">
                    <? while($row_rsAreas = mysql_fetch_assoc($rsArea)) { ?>
                        <li>
                            <a href="area.php?id=<?=$row_rsAreas['area_id'];?>"><?=$row_rsAreas['area_titulo'];?></a>
                        </li>
                    <? } ?>
                </ul>
</li>

CSS:

.dropdown-areas {
    text-align: left;
    background-color: rgba(54, 52, 53, 0.9);
    padding: 10px 0;
    width: 100%;
    display: none;
    position: absolute;
}
.dropdown-areas li {
   padding: 10px 0 10px 20px;
   width: 100%;
   list-style-type: none;
}
.dropdown-areas li a {
    border-left: 3px solid var(--corFont);
    padding-left: 10px;
}

SCRIPT:

$(document).ready(function() {
    $('#showDropdown').hover(function() {
        $('.dropdown-areas').slideToggle(1000);
    });
});
    
asked by anonymous 13.11.2018 / 13:36

2 answers

4

The .hover method fires 2 events: mouseenter and mouseleave . When using only 1 function in the method, you execute the same code ( .slideToggle() ) 2 times, which causes bug, because it will queue the animation where one will run over another.

Instead, treat events within .hover separately, each with its function:

$('#showDropdown').hover(
   function(){
      // AQUI TRATA O MOUSEENTER
   },
   function(){
      // AQUI TRATA O MOUSELEAVE
   }
);

Instead of using .slideToggle() , use .slideDown() in mouseenter and .slideUp() in mouseleave .

And to avoid even more bugs, put a if into the first function by checking if the element is invisible before applying the animation that shows the element.

Your code looks like this:

$(document).ready(function() {
   $('#showDropdown').hover(
      function() {
         if(!$('.dropdown-areas').is(":visible"))
         $('.dropdown-areas').slideDown(1000);
      },
      function() {
         $('.dropdown-areas').slideUp(1000);
      }
   );
});
.dropdown-areas {
    text-align: left;
    background-color: rgba(54, 52, 53, 0.9);
    padding: 10px 0;
    width: 100%;
    display: none;
    position: absolute;
}
.dropdown-areas li {
   padding: 10px 0 10px 20px;
   width: 100%;
   list-style-type: none;
}
.dropdown-areas li a {
    border-left: 3px solid var(--corFont);
    padding-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><liid="showDropdown" <?=$page=='areas.php' ? 'class="active"' : '';?>>
    <a class="areas" href="Javascript:void(0);">ÁREAS DE ATUAÇÃO</a>
    <ul class="dropdown-areas">
        <? while($row_rsAreas = mysql_fetch_assoc($rsArea)) { ?>
            <li>
                <a href="area.php?id=<?=$row_rsAreas['area_id'];?>"><?=$row_rsAreas['area_titulo'];?></a>
            </li>
        <? } ?>
    </ul>
</li>

You can also use the .stop () method on each function before applying the slide. This excludes the use of if in the first function:

$(document).ready(function() {
   $('#showDropdown').hover(
      function() {
         $('.dropdown-areas').stop().slideDown(1000);
      },
      function() {
         $('.dropdown-areas').stop().slideUp(1000);
      }
   );
});
.dropdown-areas {
    text-align: left;
    background-color: rgba(54, 52, 53, 0.9);
    padding: 10px 0;
    width: 100%;
    display: none;
    position: absolute;
}
.dropdown-areas li {
   padding: 10px 0 10px 20px;
   width: 100%;
   list-style-type: none;
}
.dropdown-areas li a {
    border-left: 3px solid var(--corFont);
    padding-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><liid="showDropdown" <?=$page=='areas.php' ? 'class="active"' : '';?>>
    <a class="areas" href="Javascript:void(0);">ÁREAS DE ATUAÇÃO</a>
    <ul class="dropdown-areas">
        <? while($row_rsAreas = mysql_fetch_assoc($rsArea)) { ?>
            <li>
                <a href="area.php?id=<?=$row_rsAreas['area_id'];?>"><?=$row_rsAreas['area_titulo'];?></a>
            </li>
        <? } ?>
    </ul>
</li>

Working on mobile devices (touch screen)

As these devices do not detect mouseenter , just add a .click event on the element, this time with .slideToggle() :

$('#showDropdown').click(function(){
   $('.dropdown-areas').slideToggle(1000);
});
    
13.11.2018 / 14:09
3

You can use the jQuery.stop() method to cancel the animation that is already happening before resuming the new animation.

Without stop , if the user does hover multiple times in a row quickly, the animation will continue even after the user stops interacting with the dropdown .

Test in the code below:

let dropdownAreas = $('.dropdown-areas');

$('#showDropdown').hover(
    function() {
       dropdownAreas.slideDown(500);
    },
    function() {
       dropdownAreas.slideUp(500);
    }
 );
.dropdown-areas {
    text-align: left;
    background-color: rgba(54, 52, 53, 0.9);
    padding: 10px 0;
    width: 100%;
    display: none;
    position: absolute;
}
.dropdown-areas li {
   padding: 10px 0 10px 20px;
   width: 100%;
   list-style-type: none;
}
.dropdown-areas li a {
    border-left: 3px solid var(--corFont);
    padding-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><liid="showDropdown">
    <a class="areas" href="Javascript:void(0);">ÁREAS DE ATUAÇÃO</a>
    <ul class="dropdown-areas">
            <li><a href="area.php?id=1">Área 1</a></li>
            <li><a href="area.php?id=2">Área 2</a></li>
            <li><a href="area.php?id=3">Área 3</a></li>
    </ul>
</li>

With stop , each animation cancels the previous animation. See the snippet below:

let dropdownAreas = $('.dropdown-areas');

$('#showDropdown').hover(
    function() {
       dropdownAreas.stop().slideDown(500);
    },
    function() {
       dropdownAreas.stop().slideUp(500);
    }
 );
.dropdown-areas {
    text-align: left;
    background-color: rgba(54, 52, 53, 0.9);
    padding: 10px 0;
    width: 100%;
    display: none;
    position: absolute;
}
.dropdown-areas li {
   padding: 10px 0 10px 20px;
   width: 100%;
   list-style-type: none;
}
.dropdown-areas li a {
    border-left: 3px solid var(--corFont);
    padding-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><liid="showDropdown">
    <a class="areas" href="Javascript:void(0);">ÁREAS DE ATUAÇÃO</a>
    <ul class="dropdown-areas">
            <li><a href="area.php?id=1">Área 1</a></li>
            <li><a href="area.php?id=2">Área 2</a></li>
            <li><a href="area.php?id=3">Área 3</a></li>
    </ul>
</li>
    
13.11.2018 / 14:25