web-dev-qa-db-fra.com

Animer un élément à la hauteur automatique avec jQuery

Je veux animer un <div> de 200px à auto height. Je n'arrive pas à le faire fonctionner cependant. Est-ce que quelqu'un sait comment?

Voici le code:

$("div:first").click(function(){
  $("#first").animate({
    height: "auto"
  }, 1000 );
});
166
Daniel
  1. Enregistrer la hauteur actuelle:

    var curHeight = $('#first').height();
    
  2. Réglez temporairement la hauteur sur auto:

    $('#first').css('height', 'auto');
    
  3. Obtenez la hauteur automatique:

    var autoHeight = $('#first').height();
    
  4. Revenez à curHeight et animez-le à autoHeight:

    $('#first').height(curHeight).animate({height: autoHeight}, 1000);
    

Et ensemble:

var el = $('#first'),
    curHeight = el.height(),
    autoHeight = el.css('height', 'auto').height();
el.height(curHeight).animate({height: autoHeight}, 1000);
246
David Tang

IMO c'est la solution la plus propre et la plus simple:

$("#first").animate({height: $("#first").get(0).scrollHeight}, 1000 );

Explanation: Le DOM sait déjà depuis son rendu initial quelle taille aura la div étendue quand elle est définie sur hauteur auto. Cette propriété est stockée dans le noeud DOM en tant que scrollHeight. Il suffit de récupérer l'élément DOM à partir de l'élément jQuery en appelant get(0) pour accéder à la propriété.

L'ajout d'une fonction de rappel pour définir la hauteur sur auto permet une plus grande réactivité une fois l'animation terminée (crédit chris-williams ):

$('#first').animate({
    height: $('#first').get(0).scrollHeight
}, 1000, function(){
    $(this).height('auto');
});
184
Liquinaut

C'est fondamentalement la même approche que la réponse de Box9 mais je l'ai enveloppée dans un Nice plugin jQuery that prend les mêmes arguments qu'un animate normal, pour quand vous en avez besoin paramètres plus animés et se lasser de répéter le même code à plusieurs reprises:

;(function($)
{
  $.fn.animateToAutoHeight = function(){
  var curHeight = this.css('height'),
      height = this.css('height','auto').height(),
      duration = 200,
      easing = 'swing',
      callback = $.noop,
      parameters = { height: height };
  this.css('height', curHeight);
  for (var i in arguments) {
    switch (typeof arguments[i]) {
      case 'object':
        parameters = arguments[i];
        parameters.height = height;
        break;
      case 'string':
        if (arguments[i] == 'slow' || arguments[i] == 'fast') duration = arguments[i];
        else easing = arguments[i];
        break;
      case 'number': duration = arguments[i]; break;
      case 'function': callback = arguments[i]; break;
    }
  }
  this.animate(parameters, duration, easing, function() {
    $(this).css('height', 'auto');
    callback.call(this, arguments);
  });
  return this;
  }
})(jQuery);

edit: chaînable et plus propre maintenant

24
w0ps

Une meilleure solution ne reposerait pas sur JS pour définir la hauteur de votre élément. Ce qui suit est une solution qui anime un élément à hauteur fixe en pleine hauteur ("auto"):

var $selector = $('div');
    $selector
        .data('oHeight',$selector.height())
        .css('height','auto')
        .data('nHeight',$selector.height())
        .height($selector.data('oHeight'))
        .animate({height: $selector.data('nHeight')},400);

https://Gist.github.com/202315

23
Tim Hettler

cela fonctionne et il est plus simple que les solutions avant:

CSS:

#container{
  height:143px;  
}

.max{
  height: auto;
  min-height: 143px;
}

JS:

$(document).ready(function() {
    $("#container").click(function() {      
        if($(this).hasClass("max")) {
            $(this).removeClass("max");
        } else {
            $(this).addClass("max");
        }

    })
});

Remarque: cette solution nécessite l'interface utilisateur jQuery.

11
czLukasss
var h = document.getElementById('First').scrollHeight;
$('#First').animate({ height : h+'px' },300);
8
Ignacio Martínez

Vous pouvez toujours envelopper les éléments enfants de #first et enregistrer hauteur en hauteur du wrapper sous forme de variable. Ce n'est peut-être pas la réponse la plus jolie ou la plus efficace, mais c'est ce qui se passe.

Voici un violon où j'ai inclus une réinitialisation.

mais pour vos besoins, voici la viande et les pommes de terre:

$(function(){
//wrap everything inside #first
$('#first').children().wrapAll('<div class="wrapper"></div>');
//get the height of the wrapper 
var expandedHeight = $('.wrapper').height();
//get the height of first (set to 200px however you choose)
var collapsedHeight = $('#first').height();
//when you click the element of your choice (a button in my case) #first will animate to height auto
$('button').click(function(){
    $("#first").animate({
        height: expandedHeight            
    })
});
});​
7
Usha

J'ai réussi à le réparer: D heres the code.

var divh = document.getElementById('first').offsetHeight;
$("#first").css('height', '100px');
$("div:first").click(function() {
  $("#first").animate({
    height: divh
  }, 1000);
});
5
Daniel

Utilisez slideDown et slideUp

$("div:first").click(function(){ $("#first").slideDown(1000); });
5
Ronny Sherer

Fondamentalement, la hauteur auto n'est disponible que lorsque l'élément est rendu. Si vous définissez une hauteur fixe ou si votre élément n'est pas affiché, vous ne pourrez y accéder sans astuces.

Heureusement, vous pouvez utiliser certaines astuces.

Cloner l'élément, l'afficher en dehors de la vue, lui attribuer une hauteur automatique. Vous pouvez le prendre à partir du clone et l'utiliser ultérieurement pour l'élément principal. J'utilise cette fonction et semble bien fonctionner.

jQuery.fn.animateAuto = function(prop, speed, callback){
    var elem, height, width;

    return this.each(function(i, el){
        el = jQuery(el), elem =    el.clone().css({"height":"auto","width":"auto"}).appendTo("body");
        height = elem.css("height"),
        width = elem.css("width"),
        elem.remove();

        if(prop === "height")
            el.animate({"height":height}, speed, callback);
        else if(prop === "width")
            el.animate({"width":width}, speed, callback);  
        else if(prop === "both")
            el.animate({"width":width,"height":height}, speed, callback);
    });   
}

SAGE:

$(".animateHeight").bind("click", function(e){
    $(".test").animateAuto("height", 1000); 
});

$(".animateWidth").bind("click", function(e){
    $(".test").animateAuto("width", 1000);  
});

$(".animateBoth").bind("click", function(e){
    $(".test").animateAuto("both", 1000); 
});
4
Stan George

Vous pouvez adapter la réponse de Liquinaut aux modifications de la taille de la fenêtre en ajoutant un rappel rappelant la hauteur automatique.

$("#first").animate({height: $("#first").get(0).scrollHeight}, 1000, function() {$("#first").css({height: "auto"});});
3
Cyl

tu peux toujours faire ça:

jQuery.fn.animateAuto = function(prop, speed, callback){
var elem, height, width;
return this.each(function(i, el){
    el = jQuery(el), elem = el.clone().css({"height":"auto","width":"auto"}).appendTo("body");
    height = elem.css("height"),
    width = elem.css("width"),
    elem.remove();

    if(prop === "height")
        el.animate({"height":height}, speed, callback);
    else if(prop === "width")
        el.animate({"width":width}, speed, callback);  
    else if(prop === "both")
        el.animate({"width":width,"height":height}, speed, callback);
});  
}

voici un violon: http://jsfiddle.net/Zuriel/faE9w/2/

3
Zuriel

Essaye celui-là ,

var height;
$(document).ready(function(){
    $('#first').css('height','auto');
    height = $('#first').height();
    $('#first').css('height','200px');
})

 $("div:first").click(function(){
  $("#first").animate({
    height: height
  }, 1000 );
});
2
Prakash

En voici un qui fonctionne avec BORDER-BOX ...

Salut les gars. Voici un plugin jQuery que j'ai écrit pour faire la même chose, mais qui tient également compte des différences de hauteur qui se produiront lorsque vous aurez défini box-sizing sur border-box.

J'ai également inclus un plug-in "yShrinkOut" qui masque l'élément en le rétrécissant le long de l'axe des ordonnées.


// -------------------------------------------------------------------
// Function to show an object by allowing it to grow to the given height value.
// -------------------------------------------------------------------
$.fn.yGrowIn = function (growTo, duration, whenComplete) {

    var f = whenComplete || function () { }, // default function is empty
        obj = this,
        h = growTo || 'calc', // default is to calculate height
        bbox = (obj.css('box-sizing') == 'border-box'), // check box-sizing
        d = duration || 200; // default duration is 200 ms

    obj.css('height', '0px').removeClass('hidden invisible');
    var padTop = 0 + parseInt(getComputedStyle(obj[0], null).paddingTop), // get the starting padding-top
        padBottom = 0 + parseInt(getComputedStyle(obj[0], null).paddingBottom), // get the starting padding-bottom
        padLeft = 0 + parseInt(getComputedStyle(obj[0], null).paddingLeft), // get the starting padding-left
        padRight = 0 + parseInt(getComputedStyle(obj[0], null).paddingRight); // get the starting padding-right
    obj.css('padding-top', '0px').css('padding-bottom', '0px'); // Set the padding to 0;

    // If no height was given, then calculate what the height should be.
    if(h=='calc'){ 
        var p = obj.css('position'); // get the starting object "position" style. 
        obj.css('opacity', '0'); // Set the opacity to 0 so the next actions aren't seen.
        var cssW = obj.css('width') || 'auto'; // get the CSS width if it exists.
        var w = parseInt(getComputedStyle(obj[0], null).width || 0) // calculate the computed inner-width with regard to box-sizing.
            + (!bbox ? parseInt((getComputedStyle(obj[0], null).borderRightWidth || 0)) : 0) // remove these values if using border-box.
            + (!bbox ? parseInt((getComputedStyle(obj[0], null).borderLeftWidth || 0)) : 0) // remove these values if using border-box.
            + (!bbox ? (padLeft + padRight) : 0); // remove these values if using border-box.
        obj.css('position', 'fixed'); // remove the object from the flow of the document.
        obj.css('width', w); // make sure the width remains the same. This prevents content from throwing off the height.
        obj.css('height', 'auto'); // set the height to auto for calculation.
        h = parseInt(0); // calculate the auto-height
        h += obj[0].clientHeight // calculate the computed height with regard to box-sizing.
            + (bbox ? parseInt((getComputedStyle(obj[0], null).borderTopWidth || 0)) : 0) // add these values if using border-box.
            + (bbox ? parseInt((getComputedStyle(obj[0], null).borderBottomWidth || 0)) : 0) // add these values if using border-box.
            + (bbox ? (padTop + padBottom) : 0); // add these values if using border-box.
        obj.css('height', '0px').css('position', p).css('opacity','1'); // reset the height, position, and opacity.
    };

    // animate the box. 
    //  Note: the actual duration of the animation will change depending on the box-sizing.
    //      e.g., the duration will be shorter when using padding and borders in box-sizing because
    //      the animation thread is growing (or shrinking) all three components simultaneously.
    //      This can be avoided by retrieving the calculated "duration per pixel" based on the box-sizing type,
    //      but it really isn't worth the effort.
    obj.animate({ 'height': h, 'padding-top': padTop, 'padding-bottom': padBottom }, d, 'linear', (f)());
};

// -------------------------------------------------------------------
// Function to hide an object by shrinking its height to zero.
// -------------------------------------------------------------------
$.fn.yShrinkOut = function (d,whenComplete) {
    var f = whenComplete || function () { },
        obj = this,
        padTop = 0 + parseInt(getComputedStyle(obj[0], null).paddingTop),
        padBottom = 0 + parseInt(getComputedStyle(obj[0], null).paddingBottom),
        begHeight = 0 + parseInt(obj.css('height'));

    obj.animate({ 'height': '0px', 'padding-top': 0, 'padding-bottom': 0 }, d, 'linear', function () {
            obj.addClass('hidden')
                .css('height', 0)
                .css('padding-top', padTop)
                .css('padding-bottom', padBottom);
            (f)();
        });
};

N'importe lequel des paramètres que j'ai utilisés peut être omis ou défini sur null afin d'accepter les valeurs par défaut. Les paramètres que j'ai utilisés:

  • growTo: Si vous souhaitez remplacer tous les calculs et définir la hauteur CSS à laquelle l'objet se développera, utilisez ce paramètre.
  • duration: La durée de l'animation ( évidemment ).
  • whenComplete: Une fonction à exécuter lorsque l'animation est terminée.
2
Lopsided

Basculer diapositive ( réponse de Box9 développé)

$("#click-me").click(function() {
  var el = $('#first'),
  curHeight = el.height(),
  autoHeight = el.css('height', 'auto').height(),
  finHeight = $('#first').data('click') == 1 ? "20px" : autoHeight;
  $('#first').data('click', $(this).data('click') == 1 ? false : true);
  el.height(curHeight).animate({height: finHeight});
});
#first {width: 100%;height: 20px;overflow:hidden;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="first">
  <div id="click-me">Lorem ipsum dolor sit amet, consectetur adipiscing elit</div>
  Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit,
</div>
2
che-azeh

Vos sélecteurs ne semblent pas correspondre. Votre élément a-t-il un identifiant de 'premier' ou est-ce le premier élément de chaque div?

Une solution plus sûre consisterait à utiliser 'ceci':

// assuming the div you want to animate has an ID of first
$('#first').click(function() {
  $(this).animate({ height : 'auto' }, 1000);
});
2
EMMERICH

J'avais besoin de cette fonctionnalité pour lire plusieurs zones sur une seule page, ce qui implémentait cela dans un shortcode Wordpress. J'ai rencontré le même problème.

Concevez techniquement toutes les plages lues de la page ont une hauteur fixe. Et je voulais pouvoir les développer séparément à une hauteur automatique avec une bascule. Premier clic: 'étendre à la hauteur totale de la longueur du texte', deuxième clic: 'réduire à la hauteur par défaut de 70px'

Html

 <span class="read-more" data-base="70" data-height="null">
     /* Lots of text determining the height of this span */
 </span>
 <button data-target='read-more'>Read more</button>

CSS

span.read-more {
    position:relative;
    display:block;
    overflow:hidden;
}

Donc, au-dessus de cela, l'attribut data-base dont j'ai besoin pour définir la hauteur fixe nécessaire est très simple. L'attribut data-height que j'ai utilisé pour stocker la hauteur réelle (dynamique) de l'élément.

La partie jQuery

jQuery(document).ready(function($){

  $.fn.clickToggle = function(func1, func2) {
      var funcs = [func1, func2];
      this.data('toggleclicked', 0);
      this.click(function() {
          var data = $(this).data();
          var tc = data.toggleclicked;
          $.proxy(funcs[tc], this)();
          data.toggleclicked = (tc + 1) % 2;
      });
      return this;
  };

    function setAttr_height(key) {
        $(key).each(function(){
            var setNormalHeight = $(this).height();
            $(this).attr('data-height', setNormalHeight);
            $(this).css('height', $(this).attr('data-base') + 'px' );
        });
    }
    setAttr_height('.read-more');

    $('[data-target]').clickToggle(function(){
        $(this).prev().animate({height: $(this).prev().attr('data-height')}, 200);
    }, function(){
        $(this).prev().animate({height: $(this).prev().attr('data-base')}, 200);
    });

});

J'ai d'abord utilisé une fonction clickToggle pour mes premier et deuxième clics. La seconde fonction est plus importante: setAttr_height() Tous les éléments .read-more ont leur hauteur réelle définie lors du chargement de la page dans l'attribut base-height. Ensuite, la hauteur de base est définie via la fonction css de jquery.

Avec nos deux attributs définis, nous pouvons maintenant basculer facilement entre eux. Modifiez uniquement le data-base à la hauteur désirée (fixe) et réglez la classe .read-more sur votre propre ID.

Vous pouvez tous le voir travailler dans un violon VIOLON

Aucune interface utilisateur jQuery nécessaire

1
Paul

vous pouvez le stocker dans un attribut de données.

$('.colapsable').each(function(){
    $(this).attr('data-oheight',$(this).height());
    $(this).height(100);
});

$('.colapsable h2:first-child').click(function(){
    $(this).parent('.colapsable').animate({
            height: $(this).parent('.colapsible').data('oheight')
        },500);
    }
});
1
defined media

Je publie cette réponse même si ce fil est vieux. Je ne pouvais pas obtenir la réponse acceptée pour travailler pour moi. Celui-ci fonctionne bien et est assez simple.

Je charge la hauteur de chaque div que je veux dans les données

$('div').each(function(){
    $(this).data('height',$(this).css('height'));
    $(this).css('height','20px');
});

Ensuite, je ne fais que l’utiliser pour animer au clic.

$('div').click(function(){
    $(this).css('height',$(this).data('height'));
});

J'utilise la transition CSS, donc je n'utilise pas l'animation jQuery, mais vous pouvez l'animer de la même manière.

1
Leeish

J'ai mis en place quelque chose qui fait exactement ce que je cherchais et qui a fière allure. L'utilisation de scrollHeight d'un élément vous donne la hauteur à laquelle il a été chargé dans le DOM.

 var clickers = document.querySelectorAll('.clicker');
    clickers.forEach(clicker => {
        clicker.addEventListener('click', function (e) {
            var node = e.target.parentNode.childNodes[5];
            if (node.style.height == "0px" || node.style.height == "") {
                $(node).animate({ height: node.scrollHeight });
            }
            else {
                $(node).animate({ height: 0 });
            }
        });
    });
.answer{
        font-size:15px;
        color:blue;
        height:0px;
        overflow:hidden;
       
    }
 <div class="row" style="padding-top:20px;">
                <div class="row" style="border-color:black;border-style:solid;border-radius:4px;border-width:4px;">
                    <h1>This is an animation tester?</h1>
                    <span class="clicker">click me</span>
                    <p class="answer">
                        I will be using this to display FAQ's on a website and figure you would like this.  The javascript will allow this to work on all of the FAQ divs made by my razor code.  the Scrollheight is the height of the answer element on the DOM load.  Happy Coding :)
                         Lorem ipsum dolor sit amet, mea an quis vidit autem. No mea vide inani efficiantur, mollis admodum accusata id has, eam dolore nemore eu. Mutat partiendo ea usu, pri duis vulputate eu. Vis mazim noluisse oportere id. Cum porro labore in, est accumsan euripidis scripserit ei. Albucius scaevola elaboraret usu eu. Ad sed vivendo persecuti, harum movet instructior eam ei.
                    </p>
                </div>
            </div>
            <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
0
JimmyTwoShoes