Animated dropdown with jQuery

Asked

Viewed 322 times

2

I’m developing a site, and in its header should contain a Dropdown that appears when you give a Hover in the header link, preferably with its animation coming up, but it has a bug that when you go to dropdown it tries to hide, and then appears again. With pure CSS I managed to do it without the slide animation, but I’d like to stylize it, I’ve tried it with pure CSS with Transition and the @Webkit animations.

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);
    });
});
  • 1

    Dude I think you’ll have to put a setTimeout() there to prevent the animation from starting again before you finish or stop if the user removes or goes in and out of the menu something like this... I don’t know jQuery so I couldn’t help you much in this

2 answers

4


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

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

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

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

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

Your code would look 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>
<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>

You can also use the method .stop() in each function before applying the slide. This dispenses with using the if in the first job:

$(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>
<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>

Operating on mobile devices (touch screen)

How these devices do not detect mouseenter, just add an event .click in the element, this time with .slideToggle():

$('#showDropdown').click(function(){
   $('.dropdown-areas').slideToggle(1000);
});
  • 1

    Another interesting point would be to clear the animation queue of that element with the method jQuery.stop(), otherwise animations could occur even after the user has already stopped interacting. Would $('.dropdown-areas').stop().slideDown(600); and wouldn’t need the is.(':visible') (and the same in slideup)

  • 1

    @fernandosavio obg for the tip. I will add in the answer.

  • 1

    I ended up creating an answer to complement yours (because in my only approach the use of stop). : D

  • So here it worked, just the mobile version of this same animation kind of stopped working, I should create the same one, but for the click() function it would solve this?

  • 1

    Mobile doesn’t have mouseenter and mouseleave for obvious reasons :D You would have to find another better event, perhaps touch.

  • 1

    @aleque_b Added in response. Abs!

  • And it’s working perfectly, a thank you and a hug!

Show 2 more comments

3

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

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

Take the 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>

<li id="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 the 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>

<li id="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>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.