Adding a slide effect to bootstrap dropdown

2019-01-03 12:46发布

I'm using bootstrap, and I'd like to add animation to a dropdown. I want to add an animation to it, slide down and back up when leaving it. How could I do this?

Things I tried:

Changing the Js drop down file like this:

How can I make Bootstrap's navigation dropdown slide smoothly up and down?

12条回答
手持菜刀,她持情操
2楼-- · 2019-01-03 13:14

Also it's possible to avoid using JavaScript for drop-down effect, and use CSS3 transition, by adding this small piece of code to your style:

.dropdown .dropdown-menu {
    -webkit-transition: all 0.3s;
    -moz-transition: all 0.3s;
    -ms-transition: all 0.3s;
    -o-transition: all 0.3s;
    transition: all 0.3s;

    max-height: 0;
    display: block;
    overflow: hidden;
    opacity: 0;
}

.dropdown.open .dropdown-menu {
    max-height: 300px;
    opacity: 1;
}

The only problem with this way is that you should manually specify max-height. If you set a very big value, your animation will be very quick.

It works like a charm if you know the approximate height of your dropdowns, otherwise you still can use javascript to set a precise max-height value.

Here is small example: DEMO


! There is small bug with padding in this solution, check Jacob Stamm's comment with solution.

查看更多
ゆ 、 Hurt°
3楼-- · 2019-01-03 13:14

I don't know if I can bump this thread, but I figured out a quick fix for the visual bug that happens when the open class is removed too fast. Basically, all there is to it is to add an OnComplete function inside the slideUp event and reset all active classes and attributes. Goes something like this:

Here is the result: Bootply example

Javascript/Jquery:

$(function(){
    // ADD SLIDEDOWN ANIMATION TO DROPDOWN //
    $('.dropdown').on('show.bs.dropdown', function(e){
        $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
    });

    // ADD SLIDEUP ANIMATION TO DROPDOWN //
    $('.dropdown').on('hide.bs.dropdown', function(e){
        e.preventDefault();
        $(this).find('.dropdown-menu').first().stop(true, true).slideUp(400, function(){
            //On Complete, we reset all active dropdown classes and attributes
            //This fixes the visual bug associated with the open class being removed too fast
            $('.dropdown').removeClass('open');
            $('.dropdown').find('.dropdown-toggle').attr('aria-expanded','false');
        });
    });
});
查看更多
\"骚年 ilove
4楼-- · 2019-01-03 13:17

On click it can be done using below code

$('.dropdown-toggle').click(function() {
  $(this).next('.dropdown-menu').slideToggle(500);
});
查看更多
我只想做你的唯一
5楼-- · 2019-01-03 13:22

Expanded answer, was my first answer so excuse if there wasn’t enough detail before.

For Bootstrap 3.x I personally prefer CSS animations and I've been using animate.css & along with the Bootstrap Dropdown Javascript Hooks. Although it might not have the exactly effect you're after it's a pretty flexible approach.

Step 1: Add animate.css to your page with the head tags:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.4.0/animate.min.css">

Step 2: Use the standard Bootstrap HTML on the trigger:

<div class="dropdown">
  <button type="button" data-toggle="dropdown">Dropdown trigger</button>

  <ul class="dropdown-menu">
    ...
  </ul>
</div>

Step 3: Then add 2 custom data attributes to the dropdrop-menu element; data-dropdown-in for the in animation and data-dropdown-out for the out animation. These can be any animate.css effects like fadeIn or fadeOut

<ul class="dropdown-menu" data-dropdown-in="fadeIn" data-dropdown-out="fadeOut">
......
</ul>

Step 4: Next add the following Javascript to read the data-dropdown-in/out data attributes and react to the Bootstrap Javascript API hooks/events (http://getbootstrap.com/javascript/#dropdowns-events):

var dropdownSelectors = $('.dropdown, .dropup');

// Custom function to read dropdown data
// =========================
function dropdownEffectData(target) {
  // @todo - page level global?
  var effectInDefault = null,
      effectOutDefault = null;
  var dropdown = $(target),
      dropdownMenu = $('.dropdown-menu', target);
  var parentUl = dropdown.parents('ul.nav'); 

  // If parent is ul.nav allow global effect settings
  if (parentUl.size() > 0) {
    effectInDefault = parentUl.data('dropdown-in') || null;
    effectOutDefault = parentUl.data('dropdown-out') || null;
  }

  return {
    target:       target,
    dropdown:     dropdown,
    dropdownMenu: dropdownMenu,
    effectIn:     dropdownMenu.data('dropdown-in') || effectInDefault,
    effectOut:    dropdownMenu.data('dropdown-out') || effectOutDefault,  
  };
}

// Custom function to start effect (in or out)
// =========================
function dropdownEffectStart(data, effectToStart) {
  if (effectToStart) {
    data.dropdown.addClass('dropdown-animating');
    data.dropdownMenu.addClass('animated');
    data.dropdownMenu.addClass(effectToStart);    
  }
}

// Custom function to read when animation is over
// =========================
function dropdownEffectEnd(data, callbackFunc) {
  var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
  data.dropdown.one(animationEnd, function() {
    data.dropdown.removeClass('dropdown-animating');
    data.dropdownMenu.removeClass('animated');
    data.dropdownMenu.removeClass(data.effectIn);
    data.dropdownMenu.removeClass(data.effectOut);

    // Custom callback option, used to remove open class in out effect
    if(typeof callbackFunc == 'function'){
      callbackFunc();
    }
  });
}

// Bootstrap API hooks
// =========================
dropdownSelectors.on({
  "show.bs.dropdown": function () {
    // On show, start in effect
    var dropdown = dropdownEffectData(this);
    dropdownEffectStart(dropdown, dropdown.effectIn);
  },
  "shown.bs.dropdown": function () {
    // On shown, remove in effect once complete
    var dropdown = dropdownEffectData(this);
    if (dropdown.effectIn && dropdown.effectOut) {
      dropdownEffectEnd(dropdown, function() {}); 
    }
  },  
  "hide.bs.dropdown":  function(e) {
    // On hide, start out effect
    var dropdown = dropdownEffectData(this);
    if (dropdown.effectOut) {
      e.preventDefault();   
      dropdownEffectStart(dropdown, dropdown.effectOut);   
      dropdownEffectEnd(dropdown, function() {
        dropdown.dropdown.removeClass('open');
      }); 
    }    
  }, 
});

Step 5 (optional): If you want to speed up or alter the animation you can do so with CSS like the following:

.dropdown-menu.animated {
  /* Speed up animations */
  -webkit-animation-duration: 0.55s;
  animation-duration: 0.55s;
  -webkit-animation-timing-function: ease;
  animation-timing-function: ease;
}

Wrote an article with more detail and a download if anyones interested: article: http://bootbites.com/tutorials/bootstrap-dropdown-effects-animatecss

Hope that’s helpful & this second write up has the level of detail that’s needed Tom

查看更多
我命由我不由天
6楼-- · 2019-01-03 13:23

Update 2018 Bootstrap 4

In Boostrap 4, the .open class has been replaced with .show. I wanted to implement this using only CSS transistions without the need for extra JS or jQuery...

.show > .dropdown-menu {
  max-height: 900px;
  visibility: visible;
}

.dropdown-menu {
  display: block;
  max-height: 0;
  visibility: hidden;
  transition: all 0.5s ease-in-out;
  overflow: hidden;
}

Demo: https://www.codeply.com/go/3i8LzYVfMF

Note: max-height can be set to any large value that's enough to accommodate the dropdown content.

查看更多
等我变得足够好
7楼-- · 2019-01-03 13:23

BOOTSTRAP 3 REFERENCE

Added because I keep getting caught by the solution in this thread and it stuffs me up every time.

Basically the BS dropdown immediately removes the .open class from the parent, so sliding up does not work.

Use the same bit as other solutions for slideDown();

// ADD SLIDEUP ANIMATION TO DROPDOWN //
$('.dropdown').on('hide.bs.dropdown', function(e){
  e.preventDefault();
  $(this).find('.dropdown-menu').first().stop(true, true).slideUp(300, function(){
    $(this).parent().removeClass('open');
  });
});
查看更多
登录 后发表回答