Hinzufügen eines Folieneffekts zum Bootstrap-Dropdown

80

Ich verwende Bootstrap und möchte einem Dropdown-Menü eine Animation hinzufügen. Ich möchte eine Animation hinzufügen, beim Verlassen nach unten und wieder nach oben schieben. Wie könnte ich das machen?

Dinge, die ich versucht habe:

Ändern Sie die Js-Dropdown-Datei wie folgt:

Wie kann ich das Navigations-Dropdown-Menü von Bootstrap reibungslos nach oben und unten verschieben?

Ben Beri
quelle
1
Hast du irgendwo die Datei bootstrap-dropdown.js aufgenommen? Ich sehe es nicht in der Kopfzeile .. und awwww diese Kuchen. Ich bin jetzt so hungrig!
Ablm
Hmm, es ist in boostrap.js, ich habe es aufgenommen, aber es hat nicht funktioniert, also habe ich es entfernt, aber ich habe es wieder hinzugefügt und ja, wenn ich das Mini-Gerät entferne, wird es überhaupt nicht funktionieren
Ben Beri
EDIT: oh ja, es ist enthalten.
Ablm
Umm. Die Standard-Dropdown-Liste wird nicht verschoben. In der geänderten Version (über die Links) gibt es ein $ el.parent (). SlideToggle (); Dies ruft eine JQuery-Animation auf.
Ablm
Und übrigens sehe ich nicht, warum Sie Bootstrap 2 Mal enthalten. bootstrap.min.js ist die minimierte Version.
Ablm

Antworten:

150

Wenn Sie auf Bootstrap 3 (BS3) aktualisieren, werden viele Javascript-Ereignisse angezeigt, mit denen Sie die gewünschte Funktionalität verknüpfen können. In BS3 gibt dieser Code allen Dropdown-Menüs den gewünschten Animationseffekt:

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

Sie können über BS3 Ereignisse lesen hier und speziell über die Drop - Down - Ereignisse hier .

cogell
quelle
4
Ich habe ein Problem mit dem slideUp-Teil davon. Im reduzierten Modus (Chrome) kehrt die Breite des Dropdowns zur Breite zurück, als würde sie im Vollbildmodus angezeigt. Während der Verwendung von FF wird es nach unten verschoben, aber ausgeblendet, anstatt nach oben zu rutschen.
ScubaSteve
3
Ich sehe auch dieses Problem, ich habe tatsächlich einen anderen Thread erstellt, der speziell danach fragt ... stackoverflow.com/questions/26267207/…, aber ich weiß nicht genau, wie ich es beheben soll. Ich habe das Gefühl, dass die Dropdown-Klasse nicht auf den Abschluss des Übergangs wartet, bevor sie das hidden.bs.dropdownEreignis verarbeitet.
Kyle Johnson
3
Dies funktioniert und macht, was ich will, aber im mobilen Ansichtsfenster verschwindet die Dropdown-Folie für Untermenüs zu schnell und sieht abgehackt aus - danke für die Freigabe!
Onkel Iroh
Ich kann das nicht zum Laufen bringen. Ich erhalte immer wieder den folgenden Fehler: "Nicht erfasster TypeError: $ (...). Find (...). First (...). Stop ist keine Funktion." Ich verstehe nicht, wie .stop () keine Funktion ist, es sei denn, die Animation wurde beim Auslösen des Ereignisses noch nicht gestartet. Was vermisse ich?
John
Weitere Informationen zur mobilen Lösung finden Sie in Slipochs Antwort weiter unten.
Tashows
69

Sie können auch die Verwendung von JavaScript für Dropdown-Effekte vermeiden und den CSS3-Übergang verwenden, indem Sie Ihrem Stil diesen kleinen Code hinzufügen:

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

Das einzige Problem auf diese Weise ist, dass Sie die maximale Höhe manuell angeben sollten. Wenn Sie einen sehr großen Wert festlegen, ist Ihre Animation sehr schnell.

Es funktioniert wie ein Zauber, wenn Sie die ungefähre Höhe Ihrer Dropdowns kennen. Andernfalls können Sie weiterhin Javascript verwenden, um einen genauen Wert für die maximale Höhe festzulegen.

Hier ein kleines Beispiel: DEMO


! In dieser Lösung gibt es einen kleinen Fehler beim Auffüllen. Überprüfen Sie den Kommentar von Jacob Stamm mit der Lösung.

MadisonTrash
quelle
2
Schöne Lösung, schätze es.
Lalit Narayan Mishra
Ich liebe das, aber leider funktioniert die Slide-Down-Animation nur einmal. Wenn ich das Menü schließe und es ohne Seitenaktualisierung erneut öffne, wird es sofort geöffnet. Hat noch jemand dieses Problem?
Nathan R
8
Tolle Lösung. Leider gibt es einen kleinen Fehler. Das erste Element in der Dropdown-Liste kann weiterhin angeklickt werden, auch wenn es reduziert ist. Sie können dies erkennen, indem Sie leicht unter dem ausgeblendeten Dropdown-Menü schweben. In diesem Fall keine große Sache, da Ihre erste Option Klartext ist. Wenn es sich jedoch um einen Link handelt, handelt es sich um ein Problem. Meine Lösung besteht darin, auch die Sichtbarkeit zu "animieren", aber zu verzögern, nachdem die anderen Inhalte fertig animiert sind. Probieren
Jacob Stamm
Danke, dass du auf diesen Fehler hingewiesen hast, Jacob. Es sieht so aus, als ob dies ein Problem mit dem Auffüllen der Liste ist. Wenn es Ihnen nichts ausmacht, füge ich Ihre Lösung hinzu, um zu antworten.
MadisonTrash
Dadurch wird die Animation für mich ausgeführt, aber wenn meine NavBar zusammengeklappt ist, treten einige seltsame Probleme mit der Ausrichtung / dem Abstand auf. Wissen Sie, warum / wie ich das beheben kann? Codesandbox.io/s/61vjn41mzz
Jed
24

Ich mache so etwas, aber beim Schweben statt beim Klicken. Dies ist der Code, den ich verwende. Möglicherweise können Sie ihn ein wenig optimieren, damit er beim Klicken funktioniert

$('.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()
});
Yohn
quelle
Das funktioniert super! Aber gibt es eine Möglichkeit, mit dem Mauszeiger zu arbeiten, anstatt zu klicken?
Arefin2k
Der Code, den ich oben gepostet habe, ist mit der Maus und nicht mit einem Klick.
Yohn
Gut! Vielen Dank.
Ilmk
Ich arbeite nicht für mich. Ich habe dies unter <script>Tags hinzugefügt, aber nichts ist passiert
YaddyVirus
16

Ich weiß nicht, ob ich diesen Thread stoßen kann, aber ich habe eine schnelle Lösung für den visuellen Fehler gefunden, der auftritt, wenn die offene Klasse zu schnell entfernt wird. Grundsätzlich müssen Sie lediglich eine OnComplete-Funktion in das slideUp-Ereignis einfügen und alle aktiven Klassen und Attribute zurücksetzen. Geht so etwas:

Hier ist das Ergebnis: Bootply-Beispiel

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');
        });
    });
});
IndieRok
quelle
In der Demo bleibt ein Menü offen, nachdem Sie einige hintereinander angeklickt haben.
SventoryMang
@DOTang Ja, ich denke, es war nicht perfekt, daher die schnelle Lösung, ich denke, ein wenig Refactoring würde es besser machen. Hoffentlich haben sie es behoben, wenn Bootstrap4 herauskommt
IndieRok
11

Hier ist meine Lösung für den Slide & Fade-Effekt:

   // 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:''});
      });
   });
Vedmant
quelle
Vielen Dank. Ihr Code funktioniert perfekt. Ich verstehe jedoch nicht ganz, warum wir $(this).css({'margin-top':''});@Vedmant
DucCuong
Dies dient zum Entfernen des Rand-Top-Parameters nach Abschluss der Animation, falls in Dropdowns einige Ränder in benutzerdefinierten Stilen hinzugefügt wurden (wie in meinem Thema). Es muss ohne diesen Parameter funktionieren, da es zu orig_margin_top zurück animiert, aber es ist sauberer, keine zusätzlichen zu hinterlassen Inline-Stile nach Abschluss der Animation.
Vedmant
9

Update 2018 Bootstrap 4

In Boostrap 4 wurde die .openKlasse durch ersetzt .show. Ich wollte dies nur mit CSS-Übergängen implementieren, ohne dass zusätzliches JS oder jQuery erforderlich ist ...

.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

Hinweis: max-heightKann auf einen beliebigen großen Wert eingestellt werden, der ausreicht, um den Dropdown-Inhalt aufzunehmen.

Zim
quelle
Das funktioniert perfekt. Für mich musste ich nicht einmal die maximale Höhe angeben, da ich versuchte, mit einen anderen Effekt zu erzielen margin-top.
Supreme Dolphin
Ich mag das, du brauchst nur CSS ohne ein paar JS-Codes.
Aswzen
8

Beim Klicken kann der folgende Code verwendet werden

$('.dropdown-toggle').click(function() {
  $(this).next('.dropdown-menu').slideToggle(500);
});
Abhimanyu Rana
quelle
Dies funktioniert gut, aber wenn Sie den Fokus verlieren, bleibt das Dropdown geöffnet, was nicht normal ist.
Barry Michael Doyle
7

Ich verwende den obigen Code, habe aber den Verzögerungseffekt durch slideToggle geändert.

Das Dropdown-Menü wird beim Hover mit Animation verschoben.

$('.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)
    });
Augusto Triste
quelle
1
muss es nicht zweimal definieren. Wenn Sie einen Schalter verwenden, funktioniert dies ohne den zweiten.
Dallas
3

Erweiterte Antwort, war meine erste Antwort, also entschuldigen Sie, wenn es vorher nicht genug Details gab.

Für Bootstrap 3.x bevorzuge ich persönlich CSS-Animationen und habe animate.css & zusammen mit den Bootstrap Dropdown Javascript Hooks verwendet. Obwohl es möglicherweise nicht genau den Effekt hat, den Sie suchen, ist es ein ziemlich flexibler Ansatz.

Schritt 1: Fügen Sie Ihrer Seite animate.css mit den Head-Tags hinzu:

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

Schritt 2: Verwenden Sie den Standard-Bootstrap-HTML-Code für den Trigger:

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

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

Schritt 3: Fügen Sie dann dem Dropdrop-Menüelement 2 benutzerdefinierte Datenattribute hinzu. Daten-Dropdown-In für die In-Animation und Daten-Dropdown-Out für die Out-Animation. Dies können beliebige animate.css-Effekte wie fadeIn oder fadeOut sein

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

Schritt 4: Fügen Sie als Nächstes das folgende Javascript hinzu, um die Datenattribute für Dropdown-In / Out-Daten zu lesen und auf die Hooks / Ereignisse der Bootstrap-Javascript-API ( http://getbootstrap.com/javascript/#dropdowns-events ) zu reagieren :

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');
      }); 
    }    
  }, 
});

Schritt 5 (optional): Wenn Sie die Animation beschleunigen oder ändern möchten, können Sie dies mit CSS wie folgt tun:

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

Schrieb einen Artikel mit mehr Details und einem Download, wenn jemand interessiert war: Artikel: http://bootbites.com/tutorials/bootstrap-dropdown-effects-animatecss

Ich hoffe, das ist hilfreich und dieser zweite Artikel hat die Detailgenauigkeit, die Tom benötigt

Tom James
quelle
3
Es wäre gut, zumindest einige Details in Ihre Antwort aufzunehmen - nur eine Verknüpfung mit Ihrer Website ist keine wirklich gute Antwort.
Kurz am
@GeraldSchneider hat die Antwort detaillierter aktualisiert. War meine erste Antwort auf Stackoverflow, also schätze das Feedback.
Tom James
2
$('.navbar .dropdown').hover(function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideDown();
}, function() {
    $(this).find('.dropdown-menu').first().stop(true, true).slideUp();
});

Dieser Code funktioniert, wenn Sie Dropdowns beim Hover anzeigen möchten.

Ich habe gerade das .slideTogglezu .slideDown& .slideUpund die entfernt (400)Timing

ChapDaddy65
quelle
1

Hier ist eine schöne einfache Lösung, jQuerydie gut funktioniert:

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

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

Das Umschalten der Folienanimation erfolgt beim Klicken und wird bei Verlust des Fokus immer wieder nach oben verschoben.

Ändern Sie den 300Wert nach Belieben. Je niedriger die Zahl, desto schneller die Animation.

Bearbeiten:

Diese Lösung funktioniert nur für Desktop-Ansichten. Es werden einige weitere Änderungen erforderlich sein, um eine gute Anzeige für Mobilgeräte zu ermöglichen.

Barry Michael Doyle
quelle
Dies funktioniert für mich, aber nachdem ich die Maus auf das Untermenü bewegt habe (dh weg von dropdown-toggle), verschwindet sie wieder, was bedeutet, dass ich die Untermenüpunkte nicht auswählen kann
Bassie
1

BOOTSTRAP 3 REFERENZ

Hinzugefügt, weil ich immer wieder von der Lösung in diesem Thread erwischt werde und sie mich jedes Mal voll macht.

Grundsätzlich entfernt die BS-Dropdown-Liste die .openKlasse sofort vom übergeordneten Element , sodass das Hochrutschen nicht funktioniert.

Verwenden Sie dasselbe Bit wie andere Lösungen für 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');
  });
});
Slipoch
quelle
0

Bei Bootstrap 3 macht diese Variation der obigen Antworten die mobile slideUp()Animation flüssiger. Die obigen Antworten haben eine abgehackte Animation, da Bootstrap die .openKlasse sofort vom übergeordneten Element des Umschalters entfernt , sodass dieser Code die Klasse wiederherstellt, bis die slideUp()Animation beendet ist.

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

Hauptunterschiede:

  • Im hide.bs.dropdownEvent-Handler verwende ich den .stop()Standardwert ( false) für das zweite Argument ( jumpToEnd)
  • Der hidden.bs.dropdownEreignishandler stellt die .openKlasse im übergeordneten Element des Dropdown-Umschalters wieder her und tut dies ziemlich unmittelbar nach dem ersten Entfernen der Klasse. In der Zwischenzeit wird die slideUp()Animation noch ausgeführt, und genau wie in den obigen Antworten ist der Rückruf "Die Animation ist abgeschlossen" dafür verantwortlich, dass die .openKlasse endgültig von ihrem übergeordneten Element entfernt wird .
  • Die Methoden sind miteinander verkettet, da der Selektor für jeden Ereignishandler identisch ist
Jordan Bradford
quelle