Das jQuery height Problem bei Hover + slideUp/slideDown
Stellen wir uns vor, wir haben ein Bild in dem auf Hover ein Beschreibungstext zu sehen ist. Der HTML-Code kann z.B. so aussehen:
1 2 3 4 5 | <div id="img-wrap"> <img src="foo.jpg" alt="my image" /> <p>Slide Me!</p> </div> <!-- p wird natürlich bei $(document).ready() versteckt --> |
Jetzt würde ein jeder sicherlich erstmal folgendes machen:
1 2 3 4 | $('#img-wrap').hover( function(){$(this).find('p').slideDown();}, function(){$(this).find('p').slideUp();} ); |
…oder eben mit SlideToggle, klar. Das Problem dabei tritt dann auf, wenn der Benutzer auf die seltendämliche Idee kommt den Effekt so toll zu finden, dass er Hover mehrmals schnell nacheinander auslöst. Das Resultat ist dann nämlich ein aufstauen der Animationskette, die dann erstmal Minutenlang abgearbeitet wird, auch wenn der Benutzer gar nicht mehr mit dem Element interagiert.
Die Lösung dazu heisst natürlich jQuery($el).stop(). Jegliche Animationen werden angehalten und wir können wieder sliden, ohne Animationsstau zu bekommen. Nun aber – da liegt der Knackpunkt – wird bei der Hover-Kaskade unser p-Tag unweigerlich an Höhe verlieren und irgendwann gar nicht mehr auftauchen. Denn slideDown kennt den ursprünglichen Height-Wert nicht, es bezieht sich immer ganz aktuell auf den letzten Status. Also was tun? Stop() an der falschen Stelle gesetzt? HoverIntent-Plugin benutzen? Nein, dass kann man beides getrost vergessen, es funktioniert nicht.
Der einzige Weg ist eben der etwas “hässlichere” und unbequemere, soll heißen den Anfangswert von height zu speichern und animate() zu benutzen:
1 2 3 4 5 6 7 | var $wrap = $('#img_wrap'), $p = $wrap.find('p'), p_h = $p.height(); $wrap.hover( function(){ $p.stop().animate({'height':p_h},500); }, function(){ $p.stop().animate({'height':0},500); } ); |
So you don’t have to lose height ;o)
Übrigens gibt es einen großartigen Artikel zum Thema “was man in JS alles nicht machen sollte” auf james.padolsey.com.
2 kreative Kommentare
Aufgrund interner Umstrukturierungsmaßnahmen ist es uns z.Zt. leider nicht
möglich auf neue Kommentare zu reagieren. Wir bitten dies zu entschuldigen.
Bei dringenden Rückfragen suchen Sie bitten den direkten Kontakt zu uns.
Einfacher:
$(‘#img-wrap’).hover(
function(){$(‘p’,this).stop().height(‘auto’).slideDown();},
function(){$(‘p’,this).stop().slideUp();}
);
Dank an:
http://spackmat.de/spackblog/archives/647-jQuery-Stolperstein-hover-und-slideUp-slideDown-animate.html
In den Kommentaren bei mir wies jemand darauf hin, dass es noch einfacher und sinnvoller geht:
Kommentar #10 von flex:
> mit
> .stop( true, true )
> kann man sich den Umweg schenken.
> http://api.jquery.com/stop/