88

我正在使用bootstrap,我想将动画添加到下拉列表中。我想为它添加一个动画,离开它时向下滑动并向后滑动。我怎么能这样做?

我尝试过的事情:

像这样更改 Js 下拉文件:

如何让 Bootstrap 的导航下拉菜单平滑地上下滑动?

4

16 回答 16

157

如果您更新到 Bootstrap 3 (BS3),他们会公开许多 Javascript 事件,这些事件可以很好地将您想要的功能绑定到其中。在 BS3 中,此代码将为您的所有下拉菜单提供您正在寻找的动画效果:

  // Add slideDown animation to Bootstrap dropdown when expanding.
  $('.dropdown').on('show.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
  });

  // Add slideUp animation to Bootstrap dropdown when collapsing.
  $('.dropdown').on('hide.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideUp();
  });

您可以在此处阅读有关 BS3 事件的信息,尤其是有关下拉事件的信息

于 2013-10-12T21:01:34.100 回答
81

也可以避免使用 JavaScript 来实现下拉效果,并使用 CSS3 过渡,通过将这段代码添加到您的样式中:

.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 { /* For Bootstrap 4, use .dropdown.show instead of .dropdown.open */
    max-height: 300px;
    opacity: 1;
}

这种方式的唯一问题是您应该手动指定最大高度。如果你设置一个很大的值,你的动画会很快。

如果您知道下拉菜单的大致高度,它就像一个魅力,否则您仍然可以使用 javascript 设置精确的最大高度值。

这是一个小例子:DEMO


!此解决方案中存在填充小错误,请查看 Jacob Stamm 的解决方案评论。

于 2015-08-26T17:31:42.923 回答
23

我正在做类似的事情,但悬停而不是点击..这是我正在使用的代码,你可以稍微调整一下让它在点击时工作

$('.navbar .dropdown').hover(function() {
  $(this).find('.dropdown-menu').first().stop(true, true).delay(250).slideDown();
}, function() {
  $(this).find('.dropdown-menu').first().stop(true, true).delay(100).slideUp()
});
于 2012-11-03T02:36:10.213 回答
16

我不知道我是否可以碰到这个线程,但我想出了一个快速修复开放类删除太快时发生的视觉错误的方法。基本上,它只是在 slideUp 事件中添加一个 OnComplete 函数并重置所有活动的类和属性。是这样的:

结果如下:Bootply 示例

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('show');
            $('.dropdown-menu').removeClass('show');
            $('.dropdown').find('.dropdown-toggle').attr('aria-expanded','false');
        });
    });
});
于 2015-03-10T14:54:26.853 回答
11

这是我的幻灯片和淡入淡出效果的解决方案:

   // Add slideup & fadein animation to dropdown
   $('.dropdown').on('show.bs.dropdown', function(e){
      var $dropdown = $(this).find('.dropdown-menu');
      var orig_margin_top = parseInt($dropdown.css('margin-top'));
      $dropdown.css({'margin-top': (orig_margin_top + 10) + 'px', opacity: 0}).animate({'margin-top': orig_margin_top + 'px', opacity: 1}, 300, function(){
         $(this).css({'margin-top':''});
      });
   });
   // Add slidedown & fadeout animation to dropdown
   $('.dropdown').on('hide.bs.dropdown', function(e){
      var $dropdown = $(this).find('.dropdown-menu');
      var orig_margin_top = parseInt($dropdown.css('margin-top'));
      $dropdown.css({'margin-top': orig_margin_top + 'px', opacity: 1, display: 'block'}).animate({'margin-top': (orig_margin_top + 10) + 'px', opacity: 0}, 300, function(){
         $(this).css({'margin-top':'', display:''});
      });
   });
于 2014-06-22T19:18:48.067 回答
9

点击它可以使用下面的代码完成

$('.dropdown-toggle').click(function() {
  $(this).next('.dropdown-menu').slideToggle(500);
});
于 2013-05-04T19:25:24.370 回答
9

更新 2018 引导程序 4

在 Boostrap 4 中,.open该类已被替换为.show. 我想只使用 CSS 转换来实现这一点,而不需要额外的 JS 或 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;
}

演示:https ://www.codeply.com/go/3i8LzYVfMF

注意:max-height可以设置为足以容纳下拉内容的任何大值。

于 2018-08-25T16:00:07.117 回答
7

我正在使用上面的代码,但我已经通过 slideToggle 更改了延迟效果。

它通过动画在悬停时滑动下拉菜单。

$('.navbar .dropdown').hover(function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideToggle(400);
    }, function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideToggle(400)
    });
于 2013-05-10T23:16:41.197 回答
3

扩展答案,是我的第一个答案,如果之前没有足够的细节,请原谅。

对于 Bootstrap 3.x,我个人更喜欢 CSS 动画,并且我一直在使用 animate.css 和 Bootstrap Dropdown Javascript Hooks。尽管它可能不会产生您所追求的确切效果,但它是一种非常灵活的方法。

第 1 步:使用 head 标签将 animate.css 添加到您的页面:

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

第 2 步:在触发器上使用标准 Bootstrap HTML:

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

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

步骤 3:然后在 dropdrop-menu 元素中添加 2 个自定义数据属性;data-dropdown-in 用于 in 动画和 data-dropdown-out 用于 out 动画。这些可以是任何 animate.css 效果,例如 fadeIn 或 fadeOut

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

第 4 步:接下来添加以下 Javascript 以读取 data-dropdown-in/out 数据属性并对 Bootstrap Javascript API 挂钩/事件(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');
      }); 
    }    
  }, 
});

第 5 步(可选):如果您想加快或更改动画,您可以使用 CSS 执行此操作,如下所示:

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

写了一篇更详细的文章,如果有人感兴趣,可以下载:文章:http ://bootbites.com/tutorials/bootstrap-dropdown-effects-animatecss

希望这会有所帮助,并且第二篇文章具有所需的详细程度,汤姆

于 2016-01-04T10:07:33.813 回答
3

介绍

截至撰写本文时,原始答案现在已有 8 年历史。我仍然觉得原始问题还没有适当的解决方案。

从那时起, Bootstrap已经走了很长一段路,现在是4.5.2。这个答案解决了这个版本。

到目前为止所有其他解决方案的问题

所有其他答案的问题是,当它们挂接到show.bs.dropdown/hide.bs.dropdown时,后续事件shown.bs.dropdown/hidden.bs.dropdown要么过早触发(动画仍在进行中),要么根本不触发,因为它们被抑制了(e.preventDefault())。

干净的解决方案

由于Bootstraps类中show()和的实现有一些相似之处,因此我在模仿原始行为时将它们组合在一起,并在和中添加了少量 QoL 辅助函数。以与 Bootstrap 相同的方式创建/事件。然后在动画完成后触发此事件- 正如您所期望的那样。hide()DropdowntoggleDropdownWithAnimation()showDropdownWithAnimation()hideDropdownWithAnimation()
toggleDropdownWithAnimation()shown.bs.dropdownhidden.bs.dropdown

/**
 * Toggle visibility of a dropdown with slideDown / slideUp animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {boolean} show Show (true) or hide (false) the dropdown menu.
 * @param {number} duration Duration of the animation in milliseconds
 */
function toggleDropdownWithAnimation($containerElement, show, duration = 300): void {
    // get the element that triggered the initial event
    const $toggleElement = $containerElement.find('.dropdown-toggle');
    // get the associated menu
    const $dropdownMenu = $containerElement.find('.dropdown-menu');
    // build jquery event for when the element has been completely shown
    const eventArgs = {relatedTarget: $toggleElement};
    const eventType = show ? 'shown' : 'hidden';
    const eventName = `${eventType}.bs.dropdown`;
    const jQueryEvent = $.Event(eventName, eventArgs);

    if (show) {
        // mimic bootstraps element manipulation
        $containerElement.addClass('show');
        $dropdownMenu.addClass('show');
        $toggleElement.attr('aria-expanded', 'true');
        // put focus on initial trigger element
        $toggleElement.trigger('focus');
        // start intended animation
        $dropdownMenu
            .stop() // stop any ongoing animation
            .hide() // hide element to fix initial state of element for slide down animation
            .slideDown(duration, () => {
            // fire 'shown' event
            $($toggleElement).trigger(jQueryEvent);
        });
    }
    else {
        // mimic bootstraps element manipulation
        $containerElement.removeClass('show');
        $dropdownMenu.removeClass('show');
        $toggleElement.attr('aria-expanded', 'false');
        // start intended animation
        $dropdownMenu
            .stop() // stop any ongoing animation
            .show() // show element to fix initial state of element for slide up animation
            .slideUp(duration, () => {

            // fire 'hidden' event
            $($toggleElement).trigger(jQueryEvent);
        });
    }
}

/**
 * Show a dropdown with slideDown animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {number} duration Duration of the animation in milliseconds
 */
function showDropdownWithAnimation($containerElement, duration = 300) {
    toggleDropdownWithAnimation($containerElement, true, duration);
}

/**
 * Hide a dropdown with a slideUp animation.
 * @param {JQuery} $containerElement The outer dropdown container. This is the element with the .dropdown class.
 * @param {number} duration Duration of the animation in milliseconds
 */
function hideDropdownWithAnimation($containerElement, duration = 300) {
    toggleDropdownWithAnimation($containerElement, false, duration);
}

绑定事件监听器

现在我们已经编写了适当的回调来显示/隐藏带有动画的下拉菜单,让我们实际将它们绑定到正确的事件。

我在其他答案中经常看到的一个常见错误是将事件侦听器直接绑定到元素。虽然这适用于注册事件侦听器时存在的 DOM 元素,但它不会绑定到稍后添加的元素。

这就是为什么你通常最好直接绑定到document

$(function () {

    /* Hook into the show event of a bootstrap dropdown */
    $(document).on('show.bs.dropdown', '.dropdown', function (e) {
        // prevent bootstrap from executing their event listener
        e.preventDefault();
        
        showDropdownWithAnimation($(this));
    });

    /* Hook into the hide event of a bootstrap dropdown */
    $(document).on('hide.bs.dropdown', '.dropdown', function (e) {
        // prevent bootstrap from executing their event listener
        e.preventDefault();
          
        hideDropdownWithAnimation($(this));
    });

});
于 2020-10-03T19:44:58.837 回答
2
$('.navbar .dropdown').hover(function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
}, function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideUp();
});

如果您想在悬停时显示下拉菜单,则此代码有效。

我只是将&更改.slideToggle为,并删除了时间.slideDown.slideUp(400)

于 2014-04-23T20:05:27.563 回答
1

这是一个很好的简单解决方案,使用jQuery效果很好:

$('.dropdown-toggle').click(function () {
    $(this).next('.dropdown-menu').slideToggle(300);
});

$('.dropdown-toggle').focusout(function () {
    $(this).next('.dropdown-menu').slideUp(300);
})

滑动动画切换发生在单击时,它总是在失去焦点时向后滑动。

将值更改300为您想要的任何值,数字越小动画越快。

编辑:

此解决方案仅适用于桌面视图。它需要进一步修改才能很好地显示在移动设备上。

于 2017-02-26T13:22:36.487 回答
1

引导程序 3 参考

添加是因为我一直被此线程中的解决方案所吸引,并且每次都让我感到厌烦。

基本上 BS 下拉菜单会立即.open从父级中删除该类,因此向上滑动不起作用。

使用与 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');
  });
});
于 2018-09-08T04:20:00.450 回答
1

对于 Bootstrap 3,上述答案的这种变化使移动slideUp()动画更流畅;上面的答案有断断续续的动画,因为 Bootstrap 会立即从切换的父级中删除.open该类,因此此代码会恢复该类,直到slideUp()动画完成。

// Add animations to topnav dropdowns
// based on https://stackoverflow.com/a/19339162
// and https://stackoverflow.com/a/52231970

$('.dropdown')
  .on('show.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown(300);
  })
  .on('hide.bs.dropdown', function() {
    $(this).find('.dropdown-menu').first().stop(true, false).slideUp(300, function() {
      $(this).parent().removeClass('open');
    });
  })
  .on('hidden.bs.dropdown', function() {
    $(this).addClass('open');
  });

主要区别:

  • hide.bs.dropdown事件处理程序中,我将.stop()' 的默认值 ( false) 用作其第二个参数 ( jumpToEnd)
  • hidden.bs.dropdown事件处理程序将类恢复到.open下拉切换的父级,并且在第一次删除类后几乎立即执行此操作。同时slideUp()动画仍在运行,就像上面的答案一样,它的“动画完成”回调负责最终.open从其父类中删除该类。
  • 方法链接在一起,因为每个事件处理程序的选择器是相同的
于 2019-03-12T22:58:05.210 回答
1

我建议使用 transform 而不是 max-height,它更快,并且 GPU 加速。

对于Bootstrap 5,添加以下 CSS:

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

    display: block;
    overflow: hidden;
    opacity: 0;
    transform: translateX(-25%) scaleY(0);
    transform-origin: top;
  }

  .dropdown-menu.show {
    opacity: 1;
    transform: translateX(-25%) scaleY(1);
  }

于 2021-07-13T20:39:08.183 回答
1

对于Bootstrap 5来说,一个简单而漂亮的动画幻灯片可以通过一个简单的 keframe 动画来完成。

@keyframes slideIn {
    0% {
        transform: translateY(1rem);
        opacity: 0;
    }
    100% {
        transform: translateY(0rem);
        opacity: 1;
    }
}

.slideIn {
    -webkit-animation-name: slideIn;
    animation-name: slideIn;
    animation-duration: 0.4s;
    animation-fill-mode: both;
}
<li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle m-2" href="/" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            Dropdown
          </a>
          <ul class="dropdown-menu slideIn rounded-2 p-3" aria-labelledby="navbarDropdown">
            <li><a class="dropdown-item" href="/">Action</a></li>
            <li><a class="dropdown-item" href="/">Another action</a></li>
            <li><hr class="dropdown-divider"/></li>
            <li><a class="dropdown-item" href="/">Something else here</a></li>
          </ul>
        </li>

于 2021-11-14T16:07:04.653 回答