2009-09-02 5 views
16

J'essaie d'obtenir un élément pour l'animer à sa hauteur «naturelle», c'est-à-dire la hauteur qu'il aurait si il avait height: auto;.Comment puis-je animer un élément à sa hauteur naturelle à l'aide de jQuery

Je suis venu avec ceci:

var currentHeight = $this.height(); 
$this.css('height', 'auto'); 
var height = $this.height(); 
$this.css('height', currentHeight + 'px'); 

$this.animate({'height': height}); 

Y at-il une meilleure façon de le faire? C'est comme un hack.

Editer: Voici un script complet à utiliser pour tous ceux qui veulent tester.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html lang="en"> 
    <head> 
     <title>jQuery</title> 
     <style type="text/css"> 
      p { overflow: hidden; background-color: red; border: 1px solid black; } 
      .closed { height: 1px; } 
     </style> 
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script> 
     <script type="text/javascript"> 
     $().ready(function() 
     { 
      $('div').click(function() 
      { 
       $('p').each(function() 
       { 
        var $this = $(this); 

        if ($this.hasClass('closed')) 
        { 
         var currentHeight = $this.height(); 
         $this.css('height', 'auto'); 
         var height = $this.height(); 
         $this.css('height', currentHeight + 'px'); 

         $this.animate({'height': height}); 
        } 
        else 
        { 
         $this.animate({'height': 1}); 
        } 

        $this.toggleClass('closed'); 
       }); 
      }); 
     }); 
     </script> 
    </head> 

    <body> 

     <div>Click Me</div> 
     <p>Hello - I started open</p> 
     <p class="closed">Hello - I started closed</p> 

    </body> 
</html> 
+0

ne pas oublier de var le $ cette variable Greg – redsquare

Répondre

6

Je pourrais suggérer une solution tout aussi hackish ... Clone l'élément, la position hors de vue, et obtenir sa hauteur ... puis le supprimer et animer votre original.

Cela mis à part, vous pouvez également utiliser .slideUp $() et .slideDown() $:

$this.hasClass('closed') ? $(this).slideDown() : $(this).slideUp() ; 

Si vous avez besoin de garder une ligne de 1px, vous pouvez l'appliquer avec un élément parent:

<div style='border-top:1px solid #333333'> 
    <div class='toggleMe'>Hello World</div> 
</div> 

Et appliquez le slideUp/Down sur le div .toggleMe.

+0

Semble que cela fonctionnerait mais je ne suis pas sûr que ce serait une amélioration :) Ce que j'ai fonctionne mais je suis nouveau à jQuery alors je pense qu'il doit y avoir un moyen non-hacky – Greg

+2

Vous avez décidé de ne pas utiliser $ .slideUp() et $ .slideDown()? – Sampson

+0

Je dois arrêter à 1pxhigh et je ne pense pas que ce soit possible avec ces fonctions (peut-être tort) – Greg

0
$('div').click(function() { 
    if($('p').is(':hidden')) { 
     $('p').slideUp(); 
    } else { 
     $('p').slideDown(function() { $('p').css('height','1px'); }); 
    } 
} 

Cela devrait régler la hauteur des points p à 1px une fois qu'ils ont fini de glisser.

+0

Cela définirait la hauteur de chaque p-tag à 1px. – Sampson

+0

$ (this) .css ('height', '1px'); devrait être bien alors. – Steerpike

+0

Vous l'appliquez sur le callback de la méthode slideDown(), ce qui signifie que dès qu'il est visible, il sera à nouveau masqué. Voulais-tu plutôt le régler pour le slideup? – Sampson

11

Je me permets de répondre à ce sujet, même s'il a été répondu il y a longtemps, parce que ça m'a aidé.

En fait, je ne comprends pas la première réponse: pourquoi ouvrir un élément semi-fermé pour obtenir sa hauteur, puis le refermer? Au début, vous cachez l'élément de sorte qu'une partie seulement apparaît, n'est-ce pas? Le meilleur moyen (je crois) de le faire est déjà prêt, avec javascript. Ainsi, lorsque vous cachez l'élément onready, enregistrez simplement la hauteur orig dans un var, de sorte que vous n'avez pas besoin de masquer (onready) -show-save height-hide pour pouvoir basculer la visibilité des éléments.

Regardez ce que je l'ai fait, cela fonctionne parfaitement:

$(document).ready(function(){ 
var origHeight = $("#foo").css('height'); 
$("#foo").css({"height" : "80px"}); 
$("#foo .toggle").bind("click", function(event){ toggleFoo(event, lastSearchesMidHeight); }); 
}); 

Ici, lorsque vous appelez votre fonction à bascule, vous savez ce qui est la hauteur de votre élément d'origine sans branler autour. Je l'ai écrit rapidement, espérant que cela pourrait aider quelqu'un dans le futur.

+0

C'est une bien meilleure réponse. Merci. – theorise

1

Je voudrais aussi intervenir sur ce vieux fil, si je peux, au cas où ma solution aiderait quelqu'un. Ma situation spécifique est la suivante: j'ai des div qui sont définis avec une valeur max-height qui les limite à trois lignes de hauteur, et quand l'utilisateur les survole, je veux qu'ils se développent à leur hauteur naturelle; et quand le curseur de la souris quitte le div, je veux qu'ils redescendent à la taille maximale, max-three-lines-tall. J'ai besoin d'utiliser la propriété CSS max-height, plutôt que la hauteur, parce que j'ai des div qui contiennent seulement une ou deux lignes de texte et je ne les veux pas inutilement grandes.

J'ai essayé beaucoup de solutions dans ce fil de discussion, et celle qui a fonctionné pour moi était la «suggestion hackish» impliquant des éléments clonés suggérés par Jonathan Sampson. J'ai traduit son idée dans le code suivant.N'hésitez pas à suggérer des améliorations.

Les fonctions sont déléguées à un élément parent pour gérer les div créés via un appel Ajax. La classe div.overflow_expandable a la déclaration suivante: { max-height: 5em; overflow: hidden; }

$('#results').delegate('div.overflow_expandable', 'mouseenter', function() { 
    var $this = $(this); 

    // Close any other open divs 
    $('#results div.overflow_expandable').not($(this)).trigger('mouseleave'); 

    // We need to convert the div's current natural height (which is less than 
    // or equal to its CSS max-height) to be a defined CSS 'height' property, 
    // which can then animate; and we unset max-height so that it doesn't 
    // prevent the div from growing taller. 
    if (!$this.data('originalHeight')) { 
     $this.data('originalHeight', $this.height()); 
     $this.data('originalMaxHeight', parseInt($this.css('max-height'))); 
     $this.css({ 'max-height':'none', 
      height: $this.data('originalHeight') }); 
    } 

    // Now slide out if the div is at its original height 
    // (i.e. in 'closed' state) and if its original height was equal to 
    // its original 'max-height' (so when closed, it had overflow clipped) 
    if ($this.height() == $this.data('originalHeight') && 
     $this.data('originalMaxHeight') == $this.data('originalHeight')) { 
     // To figure out the new height, clone the original element and set 
     // its height to auto, then measure the cloned element's new height; 
     // then animate our div to that height 
     var $clone = $this.clone().css({ height: 'auto', position: 'absolute', 
      zIndex: '-9999', left: '-9999px', width: $this.width() }) 
      .appendTo($this); 
     $this.animate({ height: $clone.height() }, 'slow'); 
     $clone.detach(); 
    } 
}).delegate('div.overflow_expandable', 'mouseleave', function() { 
    var $this = $(this); 
    // If the div has 'originalHeight' defined (it's been opened before) and 
    // if it's current height is greater than 'originalHeight' (it's open 
    // now), slide it back to its original height 
    if ($this.data('originalHeight') && 
     $this.height() > $this.data('originalHeight')) 
     $this.animate({ height: $this.data('originalHeight') }, 'slow'); 
}); 
1

trouvé ce post et finissent par utiliser la suggestion originale 1px de Greg - fonctionne très bien!

Ajout d'un rappel à la fonction animate, pour définir la hauteur de l'élément sur 'auto' à la fin de l'animation (dans mon cas, le contenu de cet élément spécifique pourrait changer et être plus grand).

10

la solution la plus simple que j'ai trouvée consistait simplement à envelopper l'élément de contenu avec un div limité en hauteur et réglé pour déborder: caché. Cela tronque l'élément de contenu interne à la hauteur de la div d'emballage. lorsque l'utilisateur clique, passe la souris, etc. pour afficher la hauteur totale de l'élément de contenu - il suffit d'animer la div d'emballage à la hauteur de la div contenu interne.

+0

J'adore cette solution, vraiment propre, flexible et un excellent moyen de ne pas avoir à faire de calcul js qui pourrait se casser en fonction du contenu. Top awesomeness Tobias !! –

0

Cela a fonctionné pour moi.

<div class="product-category"> 
    <div class="category-name"> 
     Cars 
    </div> 
    <div class="category-products" style="display: none; overflow: hidden;"> 
     <div class="product">Red Car</div> 
     <div class="product">Green Car</div> 
     <div class="product">Yellow Car</div> 
    </div> 
</div> 

<script type="text/javascript"> 
$(document).ready(function() { 
    $('.product-category .category-name').click(function() { 
     if ($(this).parent().hasClass('active')) { 
      $(this).parent().removeClass('active'); 
      var height = $(this).parent().find('.category-products').height(); 
      $(this).parent().find('.category-products').animate({ height : '0px' }, 600, function() { 
       $(this).parent().find('.category-products').height(height).hide(); 
      }); 
     } else { 
      $(this).parent().addClass('active'); 
      var height = $(this).parent().find('.category-products').height(); 
      $(this).parent().find('.category-products').height(0).show().animate({ height : height + 'px' }, 600); 
     } 
    }); 
}); 
</script> 
0

Ma solution est de stocker dans l'attribut data du bouton Fermer la taille originale du récipient (aurait pu être stocké aussi dans le conteneur lui-même, si vous n'utilisez pas le même bouton pour afficher également à nouveau la récipient):

$(document).ready(function(){ 
    $('.infoBox .closeBtn').toggle(hideBox, showBox); 
}); 

function hideBox() 
{ 
    var parent = $(this).parent(); 

    $(this).text('Show').data('originalHeight', parent.css('height')); 

    parent.animate({'height': 20}); 
    return false; 
} 

function showBox() 
{ 
    var parent = $(this).parent(); 

    $(this).text('Hide'); 

    parent.animate({ 
     'height': $(this).data('originalHeight') 
    }); 
    return false; 
} 
0

Je voulais pointer this answer, ce qui suggère réglage de la hauteur de "show" avec la fonction Animate(). J'ai dû modifier mon animation "slideUp" pour utiliser height: "hide" pour travailler avec.

Questions connexes