2009-09-02 7 views
16

Estoy tratando de obtener un elemento para animar a su altura "natural", es decir, la altura que tendría si tuviera height: auto;.Cómo puedo animar un elemento a su altura natural usando jQuery

Yo he llegado con esto:

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

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

¿Hay una mejor manera de hacer esto? Se siente como un truco.

Edit: Aquí hay un script completo para jugar con cualquiera que quiera probar.

<!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

no te olvides de var la $ esta variable Greg – redsquare

Respuesta

6

que podría sugerir una solución igualmente-hacker ... Clonar el elemento, coloque fuera de la vista, y obtener su altura ... entonces eliminarlo y animar a su original.

Aparte de eso, también se puede utilizar $ .slideUp() y $ .slideDown():

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

Si es necesario mantener una línea de 1 píxel, puede solicitar que con un elemento padre:

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

Y aplique el deslizamiento Arriba/Abajo en .toggleMe div.

+0

Parece que funcionaría, pero no estoy seguro de que sería una mejora :) Lo que tengo funciona pero soy nuevo en jQuery, así que estoy pensando que debe haber una forma no hacky – Greg

+2

¿Alguna razón por la que decidió no ir con $ .slideUp() y $ .slideDown()? – Sampson

+0

Necesito que se detenga a 1px de altura y no creo que eso sea posible con esas funciones (aunque podría estar equivocado) – Greg

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

Esto debería establecer que la altura de las etiquetas p sea 1px una vez que hayan terminado de deslizarse.

+0

Eso establecería la altura de cada p-tag en 1px. – Sampson

+0

$ (this) .css ('height', '1px'); debería estar bien entonces – Steerpike

+0

Lo está aplicando en la devolución de llamada del método slideDown(), lo que significa que tan pronto como sea visible, se ocultará nuevamente. ¿Pretendías configurarlo para la diapositiva? – Sampson

11

Me permito responder a este hilo, incluso si ha sido respondido hace mucho tiempo, porque me ayudó.

De hecho, no entiendo la primera respuesta: ¿por qué abrir un elemento semicerrado para obtener su altura y luego volver a cerrarlo?

Al principio, ocultas el elemento para que solo una parte aparezca, ¿verdad? La mejor forma (creo) de hacer esto ya está lista, con javascript. Entonces, cuando oculta el elemento en orden, simplemente guarde el alto de origen en una var, para que no tenga que ocultar (en curso) -show-save height-hide para poder alternar la visibilidad de los elementos.

Mira lo que hice, funciona perfectamente:

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

Aquí, cuando llama a una función activar, usted sabe cuál es su altura del elemento original sin masturbarse alrededor.

Lo escribí rápido, con la esperanza de que pueda ayudar a alguien en el futuro.

+0

Esta es una respuesta mucho mejor. Gracias. – theorise

1

También me gustaría hablar de este viejo hilo, si es posible, en caso de que mi solución ayude a alguien. Mi situación específica es la siguiente: tengo algunos div's que están configurados con un valor de altura máxima que los limita a tres líneas de altura, y cuando el usuario los sobrepasa, quiero que se expandan a su altura natural; y cuando el cursor del mouse abandona el div, quiero que retroceda hasta la altura recortada, máxima de tres líneas. Necesito usar la propiedad CSS maximum-height, en lugar de height, porque tengo algunos div que contienen solo una o dos líneas de texto y no los quiero innecesariamente altos.

Probé muchas de las soluciones en este hilo, y la que funcionó para mí fue la 'sugerencia de hackish' que involucraba elementos clonados sugeridos por Jonathan Sampson. Traducí su idea en el siguiente código.Por favor, siéntase libre de sugerir mejoras.

Las funciones se delegan en un elemento principal para manejar los div creados a través de una llamada Ajax. La clase div.overflow_expandable tiene la siguiente declaración: { 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

Encontrado este post y las usamos original de 1px sugerencia de Greg - funciona muy bien!

Acaba de agregar una devolución de llamada a la función animada, para establecer el alto del elemento en 'auto' cuando termina la animación (en mi caso, el contenido de ese elemento específico podría cambiar y ser más grande).

10

la solución más fácil que encontré fue simplemente envolver el elemento de contenido con un div que está limitado en altura y configurado para rebosar: oculto. Esto trunca el elemento de contenido interno a la altura del div de ajuste. cuando el usuario hace clic, se desplaza, etc. para mostrar la altura completa del elemento de contenido, simplemente anime el div de ajuste a la altura del div de contenido interno.

+0

Me encanta esta solución, realmente limpia, flexible y una excelente manera de evitar tener que hacer algunos cálculos js que podrían romperse dependiendo del contenido. ¡Increíble genial, Tobias! –

0

Esto funcionó para mí.

<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

Mi solución es almacenar en el atributo data del botón de cierre el tamaño original del contenedor (podría haber sido almacenada también en el propio contenedor, si no utiliza el mismo botón para mostrar también el nuevo contenedor):

$(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

quería señalar a this answer, lo que sugiere ajustar la altura de "mostrar" con la función animate(). Tuve que editar mi estilo "slideUp" animado para usar height: "hide" para trabajar con él.

Cuestiones relacionadas