Estoy usando bootstrap y me gustaría agregar animación a un menú desplegable. Quiero agregarle una animación, deslizarme hacia abajo y hacia arriba cuando lo deje. ¿Cómo podría hacer esto?
Cosas que probé:
Cambiar el archivo desplegable Js de esta manera:
javascript
drop-down-menu
twitter-bootstrap
Ben Beri
fuente
fuente
Respuestas:
Si actualiza a Bootstrap 3 (BS3), han expuesto muchos eventos de Javascript que son agradables para vincular su funcionalidad deseada. En BS3, este código le dará a todos sus menús desplegables el efecto de animación que está buscando:
// 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(); });
Puede leer acerca de los eventos BS3 aquí y específicamente sobre los eventos desplegables aquí .
fuente
hidden.bs.dropdown
evento.También es posible evitar el uso de JavaScript para el efecto desplegable y usar la transición CSS3, agregando este pequeño fragmento de código a su estilo:
.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; }
El único problema con esta forma es que debe especificar manualmente la altura máxima. Si establece un valor muy grande, su animación será muy rápida.
Funciona de maravilla si conoce la altura aproximada de sus menús desplegables; de lo contrario, aún puede usar javascript para establecer un valor preciso de altura máxima.
Aquí hay un pequeño ejemplo: DEMO
! Hay un pequeño error con el relleno en esta solución, verifique el comentario de Jacob Stamm con la solución.
fuente
pointer-events:none
a la versión contraída, luego agregarpoint-events: all
al menú una vez que lo haya hecho.show
Estoy haciendo algo así, pero al pasar el mouse en lugar de hacer clic. Este es el código que estoy usando, es posible que pueda modificarlo un poco para que funcione al hacer clic
$('.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() });
fuente
<script>
No sé si puedo superar este hilo, pero descubrí una solución rápida para el error visual que ocurre cuando la clase abierta se elimina demasiado rápido. Básicamente, todo lo que hay que hacer es agregar una función OnComplete dentro del evento slideUp y restablecer todas las clases y atributos activos. Va algo como esto:
Aquí está el resultado: Ejemplo de 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'); }); }); });
fuente
aquí está mi solución para el efecto de deslizamiento y desvanecimiento:
// 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:''}); }); });
fuente
$(this).css({'margin-top':''});
@VedmantActualización 2018 Bootstrap 4
En Boostrap 4, la
.open
clase ha sido reemplazada por.show
. Quería implementar esto usando solo transiciones CSS sin la necesidad de JS o jQuery adicional ....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; }
Demostración: https://www.codeply.com/go/3i8LzYVfMF
Nota:
max-height
se puede establecer en cualquier valor grande que sea suficiente para acomodar el contenido desplegable.fuente
margin-top
.Al hacer clic, se puede hacer usando el siguiente código
$('.dropdown-toggle').click(function() { $(this).next('.dropdown-menu').slideToggle(500); });
fuente
Estoy usando el código anterior, pero he cambiado el efecto de retardo mediante slideToggle.
Desliza el menú desplegable al pasar el mouse con animación.
$('.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) });
fuente
Respuesta ampliada, fue mi primera respuesta, así que disculpe si no había suficientes detalles antes.
Para Bootstrap 3.x, personalmente prefiero las animaciones CSS y he estado usando animate.css y junto con Bootstrap Dropdown Javascript Hooks. Aunque puede que no tenga exactamente el efecto que busca, es un enfoque bastante flexible.
Paso 1: agregue animate.css a su página con las etiquetas de encabezado:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.4.0/animate.min.css">
Paso 2: use el HTML Bootstrap estándar en el disparador:
<div class="dropdown"> <button type="button" data-toggle="dropdown">Dropdown trigger</button> <ul class="dropdown-menu"> ... </ul> </div>
Paso 3: luego agregue 2 atributos de datos personalizados al elemento del menú desplegable; menú desplegable de datos para la animación de entrada y menú desplegable de datos para la animación de salida. Estos pueden ser efectos de animate.css como fadeIn o fadeOut
<ul class="dropdown-menu" data-dropdown-in="fadeIn" data-dropdown-out="fadeOut"> ...... </ul>
Paso 4: A continuación, agregue el siguiente Javascript para leer los atributos de datos de entrada / salida del menú desplegable de datos y reaccionar a los eventos / ganchos de la API de JavaScript de Bootstrap ( 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'); }); } }, });
Paso 5 (opcional): si desea acelerar o alterar la animación, puede hacerlo con CSS como el siguiente:
.dropdown-menu.animated { /* Speed up animations */ -webkit-animation-duration: 0.55s; animation-duration: 0.55s; -webkit-animation-timing-function: ease; animation-timing-function: ease; }
Escribió un artículo con más detalles y una descarga si alguien está interesado: artículo: http://bootbites.com/tutorials/bootstrap-dropdown-effects-animatecss
Espero que sea útil y que este segundo artículo tenga el nivel de detalle que se necesita Tom
fuente
$('.navbar .dropdown').hover(function() { $(this).find('.dropdown-menu').first().stop(true, true).slideDown(); }, function() { $(this).find('.dropdown-menu').first().stop(true, true).slideUp(); });
Este código funciona si desea mostrar menús desplegables al pasar el mouse.
Acabo de cambiar
.slideToggle
a.slideDown
&.slideUp
, y eliminé el(400)
tiempofuente
Aquí hay una solución simple y agradable
jQuery
que funciona muy bien:$('.dropdown-toggle').click(function () { $(this).next('.dropdown-menu').slideToggle(300); }); $('.dropdown-toggle').focusout(function () { $(this).next('.dropdown-menu').slideUp(300); })
La alternancia de la animación de diapositivas se produce al hacer clic y siempre se desliza hacia arriba al perder el enfoque.
Cambie el
300
valor a lo que desee, cuanto menor sea el número, más rápida será la animación.Editar:
Esta solución solo funcionará para vistas de escritorio. Necesitará algunas modificaciones adicionales para que se muestre bien en dispositivos móviles.
fuente
dropdown-toggle
), desaparece nuevamente, lo que significa que no puedo seleccionar los elementos del submenúREFERENCIA DE BOOTSTRAP 3
Agregado porque sigo siendo atrapado por la solución en este hilo y me llena todo el tiempo.
Básicamente, el menú desplegable BS elimina inmediatamente la
.open
clase del padre, por lo que deslizarse hacia arriba no funciona.Utilice el mismo bit que otras soluciones para 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'); }); });
fuente
Para Bootstrap 3, esta variación de las respuestas anteriores hace que la
slideUp()
animación móvil sea más fluida; las respuestas anteriores tienen una animación entrecortada porque Bootstrap elimina la.open
clase del padre del conmutador inmediatamente, por lo que este código restaura la clase hasta queslideUp()
finaliza la animación.// 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'); });
Diferencias clave:
hide.bs.dropdown
controlador de eventos estoy usando.stop()
el valor predeterminado (false
) para su segundo argumento (jumpToEnd
)hidden.bs.dropdown
controlador de eventos restaura la.open
clase al padre del conmutador desplegable, y lo hace prácticamente inmediatamente después de que la clase se haya eliminado por primera vez. Mientras tanto, laslideUp()
animación todavía se está ejecutando, y al igual que en las respuestas anteriores, su devolución de llamada "the-animation-is-complete" es responsable de eliminar finalmente la.open
clase de su padre.fuente
Intro
En el momento de redactar este informe, la respuesta original tiene ahora 8 años. Aún así, siento que aún no hay una solución adecuada a la pregunta original.
Bootstrap ha recorrido un largo camino desde entonces y ahora está en 4.5.2 . Esta respuesta aborda esta misma versión.
El problema con todas las demás soluciones hasta ahora
El problema con todas las demás respuestas es que, si bien se conectan a
show.bs.dropdown
/hide.bs.dropdown
, los eventos de seguimientoshown.bs.dropdown
/hidden.bs.dropdown
se activan demasiado pronto (la animación aún está en curso) o no se activan en absoluto porque se suprimieron (e.preventDefault()
).Una solucion limpia
Dado que la implementación de
show()
yhide()
en laDropdown
clase Bootstraps comparte algunas similitudes, las he agrupadotoggleDropdownWithAnimation()
al imitar el comportamiento original y agregué pequeñas funciones de ayuda de QoL ashowDropdownWithAnimation()
yhideDropdownWithAnimation()
.toggleDropdownWithAnimation()
crea un eventoshown.bs.dropdown
/ dehidden.bs.dropdown
la misma manera que Bootstrap lo hace. Este evento se activa luego de que se completa la animación, tal como era de esperar./** * 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); }
Vincular oyentes de eventos
Ahora que hemos escrito las devoluciones de llamada adecuadas para mostrar / ocultar un menú desplegable con una animación, vamos a vincularlas a los eventos correctos.
Un error común que he visto mucho en otras respuestas es vincular a los oyentes de eventos a los elementos directamente. Si bien esto funciona bien para los elementos DOM presentes en el momento en que se registra el detector de eventos, no se vincula a los elementos agregados más adelante.
Es por eso que generalmente es mejor vincularse directamente a
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)); }); });
fuente