2009-09-02 14 views
16

Sto cercando di ottenere un elemento da animare alla sua altezza "naturale" - cioè l'altezza sarebbe se avesse height: auto;.Come posso animare un elemento alla sua altezza naturale usando jQuery

mi è venuta in mente questo:

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

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

Esiste un modo migliore per fare questo? Sembra un po 'un trucco.

Modifica: Ecco uno script completo con cui giocare per chiunque voglia testare.

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

Non dimenticate di varare $ questa variabile Greg – redsquare

risposta

6

potrei suggerire una soluzione ugualmente-hacker ... Clonare l'elemento, posizionarlo fuori dalla vista, e ottenere la sua altezza ... quindi eliminarlo e animare l'originale.

A parte questo, si potrebbe anche usare $ .slideUp() e $ .slideDown():

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

Se è necessario mantenere una linea di 1px, è possibile applicare che con un elemento padre:

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

E applicare lo slidingUp/Down sul .toggleMe div.

+0

Sembra che funzionerebbe ma non sono sicuro che sarebbe un miglioramento :) Ciò che ho funziona, ma sono nuovo di jQuery, quindi sto pensando che ci deve essere un modo non hacking – Greg

+2

Qualsiasi motivo hai deciso di non andare con $ .slideUp() e $ .slideDown()? – Sampson

+0

Ho bisogno che si fermi a 1px heigh e non penso che sia possibile con quelle funzioni (potrebbe essere sbagliato però) – Greg

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

Questo dovrebbe impostare l'altezza dei tag p su 1px una volta terminato lo scorrimento.

+0

Ciò imposterebbe l'altezza di ogni tag p su 1px. – Sampson

+0

$ (this) .css ('height', '1px'); dovrebbe andare bene allora – Steerpike

+0

Lo stai applicando al callback del metodo slideDown(), che significa che non appena sarà visibile, sarà nascosto di nuovo. Intendevi invece impostarlo per la diapositiva? – Sampson

11

Mi permetto di rispondere a questa discussione, anche se è stata risposta molto tempo fa, perché mi ha semplicemente aiutato.

In effetti, non capisco la prima risposta: perché aprire un elemento semichiuso per ottenere la sua altezza, e quindi chiuderlo di nuovo?

All'inizio, si nasconde l'elemento in modo che appaia solo una parte di esso, giusto? Il modo migliore (credo) di farlo è già, con javascript. Quindi, quando si nasconde già l'elemento, è sufficiente salvare l'altezza orig in una var, in modo da non dover nascondere (onready) -show-save height-hide per poter attivare la visibilità degli elementi.

Guardate quello che ho fatto, funziona perfettamente:

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

Qui, quando si chiama la funzione di commutazione, si sa che cosa è la vostra altezza elemento originale senza masturba in giro.

L'ho scritto velocemente, sperando che potesse aiutare qualcuno in futuro.

+0

Questa è una risposta molto migliore. Grazie. – theorise

1

Mi piacerebbe anche inserirmi in questo vecchio thread, se possibile, nel caso in cui la mia soluzione aiuti chiunque. La mia situazione specifica è questa: ho alcuni div che sono impostati con un valore di altezza massima che li limita a tre linee di altezza, e quando l'utente li toglie li voglio espandere alla loro altezza naturale; e quando il cursore del mouse lascia il div, voglio che si restringano verso il basso fino all'altezza massima trilineata. Ho bisogno di usare la proprietà max-height del CSS, piuttosto che height, perché ho alcune div che contengono solo una o due righe di testo e non le voglio eccessivamente alte.

Ho provato molte delle soluzioni in questo thread e quello che ha funzionato per me è stato il 'suggerimento hackish' che implicava elementi clonati suggeriti da Jonathan Sampson. Ho tradotto la sua idea nel seguente codice.Non esitate a suggerire miglioramenti.

Le funzioni sono delegate a un elemento padre per gestire i div creati tramite una chiamata Ajax. La classe div.overflow_expandable ha la seguente dichiarazione: { 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

trovato questo post e finire con originale 1px suggerimento di Greg - grandi opere!

Appena aggiunto un richiamo alla funzione animate, per impostare l'altezza dell'elemento su "auto" quando termina l'animazione (nel mio caso, il contenuto di quell'elemento specifico potrebbe cambiare ed essere più grande).

10

la soluzione più semplice che ho trovato era semplicemente avvolgere l'elemento di contenuto con un div che è limitato in altezza e impostato su overflow: nascosto. Questo tronca l'elemento di contenuto interno all'altezza del div wrapping. quando l'utente fa clic, passa con il mouse, ecc. per mostrare l'altezza completa dell'elemento di contenuto: è sufficiente animare il div di avvolgimento all'altezza del div del contenuto interno.

+0

Adoro questa soluzione, davvero pulita, flessibile e un modo eccellente per evitare di dover fare qualche calcolo js che potrebbe rompersi a seconda del contenuto. Top awesomeness Tobias !! –

0

Questo ha funzionato per me.

<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

La mia soluzione è quello di memorizzare l'attributo data del pulsante di chiusura le dimensioni originali del contenitore (avrebbe potuto essere memorizzati anche nel contenitore stesso, se non si utilizza lo stesso pulsante per visualizzare anche il nuovo contenitore):

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

volevo segnalare a this answer, che suggeriscono impostare l'altezza a "spettacolo" con la funzione animate(). Ho dovuto modificare il mio stile "slide-up" per utilizzare l'altezza: "nascondi" per lavorare con esso.

Problemi correlati