90 votes

Ajout d'un effet de glissement à la liste déroulante bootstrap

J'utilise bootstrap et j'aimerais ajouter une animation à une liste déroulante. Je veux ajouter une animation à celle-ci, glisser vers le bas et remonter en la quittant. Comment puis-je faire cela ?

Les choses que j'ai essayées :

En changeant le fichier déroulant Js comme ceci :

Comment faire en sorte que le menu déroulant de navigation de Bootstrap glisse en douceur vers le haut et vers le bas ?

9voto

Abhimanyu Rana Points 91

En cliquant, vous pouvez utiliser le code suivant

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

9voto

Skelly Points 27772

Mise à jour 2018 Bootstrap 4

Dans Boostrap 4, le .open a été remplacée par la classe .show . Je voulais mettre en œuvre ce système en utilisant uniquement des transitions CSS sans avoir besoin de JS ou de jQuery supplémentaires...

.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;
}

Démonstration : https://www.codeply.com/go/3i8LzYVfMF

Nota: max-height peut être fixé à n'importe quelle valeur suffisamment grande pour contenir le contenu de la liste déroulante.

7voto

Augusto Triste Points 78

J'utilise le code ci-dessus mais j'ai changé l'effet de délai par slideToggle.

Il fait glisser la liste déroulante au survol avec une animation.

$('.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)
    });

3voto

Tom James Points 116

Réponse élargie, c'était ma première réponse donc excusez moi s'il n'y avait pas assez de détails avant.

Pour Bootstrap 3.x, je préfère personnellement les animations CSS et j'ai utilisé animate.css & ainsi que les crochets Javascript de Bootstrap Dropdown. Bien que cela n'ait pas exactement l'effet que vous recherchez, c'est une approche assez flexible.

Étape 1 : Ajoutez animate.css à votre page avec les balises head :

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

Étape 2 : Utilisez le HTML Bootstrap standard sur le déclencheur :

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

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

Étape 3 : Ajoutez ensuite deux attributs de données personnalisés à l'élément dropdrop-menu : data-dropdown-in pour l'animation d'entrée et data-dropdown-out pour l'animation de sortie. Il peut s'agir de n'importe quel effet animate.css comme fadeIn ou fadeOut.

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

Étape 4 : Ajoutez ensuite le Javascript suivant pour lire les attributs de données data-dropdown-in/out et réagir aux crochets/événements de l'API 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');
      }); 
    }    
  }, 
});

Étape 5 (facultative) : Si vous souhaitez accélérer ou modifier l'animation, vous pouvez le faire à l'aide d'une feuille de style CSS comme celle-ci :

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

J'ai écrit un article avec plus de détails et un téléchargement si quelqu'un est intéressé : article : http://bootbites.com/tutorials/bootstrap-dropdown-effects-animatecss

J'espère que cela vous aidera et que ce deuxième rapport contient le niveau de détail nécessaire. Tom

3voto

Tobias Wicker Points 43

Intro

Au moment où nous écrivons ces lignes, la réponse originale a maintenant 8 ans. J'ai toujours l'impression qu'il n'y a pas encore de solution appropriée à la question originale.

Bootstrap a parcouru un long chemin depuis lors et se trouve aujourd'hui à 4.5.2 . Cette réponse traite précisément de cette version.

Le problème avec toutes les autres solutions jusqu'à présent

Le problème avec toutes les autres réponses est que, bien qu'elles soient liées à show.bs.dropdown / hide.bs.dropdown les événements de suivi shown.bs.dropdown / hidden.bs.dropdown sont soit tirés trop tôt (animation toujours en cours), soit ils ne tirent pas du tout parce qu'ils ont été supprimés ( e.preventDefault() ).

Une solution propre

Depuis la mise en œuvre de l show() y hide() dans Bootstraps Dropdown partagent certaines similitudes, je les ai regroupés en toggleDropdownWithAnimation() lors de l'imitation du comportement original et ajouté de petites fonctions d'aide à la qualité de vie pour showDropdownWithAnimation() y hideDropdownWithAnimation() .
toggleDropdownWithAnimation() crée un shown.bs.dropdown / hidden.bs.dropdown de la même manière que Bootstrap. Cet événement est ensuite déclenché après l'animation s'est terminée - comme on pouvait s'y attendre.

/**
 * 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);
}

Lier les récepteurs d'événements

Maintenant que nous avons écrit les rappels appropriés pour afficher/masquer une liste déroulante avec une animation, nous allons les lier aux événements appropriés.

Une erreur commune que j'ai souvent vue dans d'autres réponses est de lier directement les écouteurs d'événements aux éléments. Si cela fonctionne bien pour les éléments du DOM présents au moment de l'enregistrement de l'écouteur d'événements, cela ne lie pas les éléments ajoutés ultérieurement.

C'est la raison pour laquelle il est généralement préférable de se lier directement à l'autorité de certification. 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));
    });

});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X