Abro, November 2009

Das jQuery height Problem bei Hover + slideUp/slideDown

jQuery Hover+Slide = lose height

Ich mag kurz auf ein häufiges Problem hinweisen, welches einen ganz gerne überkommt wenn man mit Hover und jQuery.slideUp() / jQuery.slideDown() arbeitet. Im Grunde ist es nichts dramatisches, aber ich habe es bekanntermaßen doch lieber sauber:


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

  1. bobosch, 28.04.2011 17:27h

    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

  2. Nathanael, 26.08.2011 16:18h

    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/

Kommentare sind geschlossen.
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.
Das Unternehmen Lucido Media GbR wurde am 31.12.2013 stillgelegt. Diese Website existiert weiterhin zu Archivzwecken. Der Gesellschafter Daniel Abromeit führt seine Arbeit ab sofort unter dem Dach der Agentur Koch Essen fort. Für entsprechende Anfragen wenden Sie sich daher bitte an http://koch-essen.de/kontakt/