使用jQuery将元素动画化为自动高度


171

我想动画一个<div>200pxauto的高度。我似乎无法使其工作。有人知道吗?

这是代码:

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

14
您应将最佳答案标记为已接受。
kleinfreund


@IanMackinnon这个问题肯定有更好的答案。我已经关闭了该问题,以作为重复。
马达拉的鬼魂2015年

Answers:


254
  1. 保存当前高度:

    var curHeight = $('#first').height();
  2. 暂时将高度切换为自动:

    $('#first').css('height', 'auto');
  3. 获取自动高度:

    var autoHeight = $('#first').height();
  4. 切换回curHeight并设置动画autoHeight

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

并在一起:

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

@Daniel,您的JS代码在哪里?发布该位以及显示您所引用元素的HTML部分。
David Tang

21
.animated({height: autoHeight}, 1000, function(){ el.height('auto'); });
可行

注意在响应式设计上设置固定高度。如果用户调整屏幕大小,它将变成一团糟。动画完成后,最好将高度设置为“自动”。
乔纳森·汤格

4
这有可能导致FOUC。在进行动画制作之前,用户可能会看到该元素跳到全高一秒钟。
Dingredient 2014年

1
您可以通过opacity: 0; position: absolute;在测量元素时先给出元素并在完成后将其删除来防止FOUC(“未样式化内容的闪烁”)。
雅各布·伊芙琳

194

IMO这是最干净,最简单的解决方案:

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

说明:DOM已经从其初始渲染中知道了将div设置为auto height时扩展div的大小。此属性以形式存储在DOM节点中scrollHeight。我们只需要通过调用从jQuery元素中获取DOM元素即可get(0),然后就可以访问该属性。

添加回调函数以将高度设置为自动可在动画完成后提供更高的响应度(来源:chris-williams):

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


1
根据盒模型的定义,裕度不是对象高度的一部分。不过,您始终可以自己添加边距。
Liquinaut 2015年

22
这应该是公认的答案,因为它在没有任何闪烁的情况下效果最佳,并且确实做得很好
Einius

7
我也认为这是最好的解决方案。我会在其中添加一个回调函数来将高度设置为自动以提高响应速度。 $('#first').animate({ height: $('#first').get(0).scrollHeight }, 1000, function() { $(this).height('auto'); });
克里斯·威廉姆斯

1
哇,这真是太优雅了。它也适用scrollWidth于宽度动画。
2015年

24

这基本上与Box9的答案相同,但是我将其包装在一个不错的jquery插件中插件采用与常规动画相同的参数备不时之需,当您需要更多的动画参数并且不厌其烦地重复执行相同的代码时:

;(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);

编辑:现在可链接和更清洁


23

更好的解决方案将不依赖JS来设置元素的高度。以下是将固定高度元素设置为全(“自动”)高度的动画解决方案:

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/2023150


2
这个单行代码不容易理解,也许写几行代码会对其他人有所帮助。
Jaap 2012年

这是最佳解决方案,因为如果用户调整窗口大小,自动高度可能会改变。参见以下内容://动画过滤器函数的高度toggleSlider(){如果($('#filters')。height()!= 0){$('#filters')。animate({height:'0 '}); } else {var $ selector = $('#filters'); $ selector .data('oHeight',$ selector.height()).css('height','auto').data('nHeight',$ selector.height()).height($ selector.data(' oHeight')).animate({height:$ selector.data('nHeight')},400); }; console.log('agg'); }
Ricky 2014年

可以使div打开,但不会动画超过400ms。也许我还有其他设置,但是只是一瞬间打开。
ntgCleaner

可以,但是设置height为固定值(例如122px)。我的元素在一段时间后更改了高度,因此我不得不用选项替换duration参数(400){duration: 400, complete: function() {$selector.css('height', 'auto');}}
jsruok

12

这是可行的,然后比以下解决方案更简单:

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");
        }

    })
});

注意:此解决方案需要jQuery UI


1
应该提到的是,这需要Jquery UI插件,而最初的问题仅涉及jquery。但是,如果您使用的是Jquery UI,则可以使用。
user56reinstatemonica8'8

4
您还可以使用$(this).toggleClass('max',250); 而不是使用if语句
Antoine Hedgecock 2014年

1
为什么在.addClass和中包含第二个值.removeClass
bowl0stu


7

您始终可以包装#first的子元素,并将包装器的height height保存为变量。这可能不是最漂亮或最有效的答案,但却可以解决问题。

这是一个小提琴,其中包括一个重置。

但出于您的目的,这是肉和土豆:

$(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            
    })
});
});​


5

我设法解决它:D这是代码。

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

4

您可以通过添加将高度重新设置为自动的回调来使Liquinaut的答案响应于窗口大小的变化。

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

4

基本上,高度自动仅在渲染元素后才可用。如果设置了固定的高度,或者没有显示元素,则没有任何技巧就无法访问它。

幸运的是,您可以使用一些技巧。

克隆元素,将其显示在视图外部,并为其自动设置高度,您可以从克隆中获取它,并稍后将其用于主要元素。我使用此功能,并且似乎工作良好。

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);
    });   
}

用法:

$(".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); 
});

1
如果您不想使用该功能,请执行以下操作:var clone = element.clone()clone.appendTo('body')clone.css('height','auto')var itemHeight = clone.outerHeight( ); clone.remove()现在在itemHeight变量中具有项目的高度,因此您不仅可以将其用于动画。
Stan George

3

您可以随时这样做:

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);
});  
}

这是一个小提琴:http : //jsfiddle.net/Zuriel/faE9w/2/


1
您可以替换:.appendTo("body")作者.appendTo(el.parent())
Steffi,2014年

2

您的选择器似乎不匹配。您的元素的ID是否为“ first”,还是每个div中的第一个元素?

一个更安全的解决方案是使用'this':

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

1
啊。好吧,看来您已经找到了解决方案。为了安全起见,我仍将$(this)在您的点击处理程序内使用。
EMMERICH,2011年

10
animate({height: 'auto'})没有任何作用。至少不是jQuery 1.6.4。
贾尼斯·埃默里斯(JānisElmeris)2012年

2

试试这个,

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 );
});

这是行不通的,您只能在ready函数中访问var的高度。
meo

在ready函数之前定义高度,并且只使用高度而不是var height ..这样,它可能会发挥作用丹尼尔
Prakash

2

这是与BORDER-BOX一起使用的...

嗨,大家好。这里是一个jQuery插件,我写做相同,但也占到当你将要发生的高差box-sizing设置border-box

我还包括一个“ yShrinkOut”插件,该插件通过沿y轴收缩元素来隐藏元素。


// -------------------------------------------------------------------
// 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)();
        });
};

我使用的任何参数都可以省略或设置为null以便接受默认值。我使用的参数:

  • growTo:如果要覆盖所有计算并设置对象将增长到的CSS高度,请使用此参数。
  • 持续时间:动画的持续时间(显然)。
  • whenComplete:动画完成时运行的函数。

2

切换幻灯片(Box9的答案已扩展)

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


1

即使此线程很旧,我仍在发布此答案。我无法获得可接受的答案来为我工作。这个很好用,非常简单。

我将想要的每个div的高度加载到数据中

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

然后在点击动画时就使用它。

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

我正在使用CSS过渡,所以我不使用jQuery动画,但是您可以使用相同的动画。


1

您可以将其存储在数据属性中。

$('.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);
    }
});

基本上与Hettler的一支衬管相同,但更易于理解。
Timothy Groote 2015年

1

我需要此功能来实现一页上多个阅读区域的实现,并将其实现为Wordpress短代码,但遇到了同样的问题。

从技术上讲,页面上所有跨度阅读器的高度都具有固定的高度。而且我希望能够通过切换将它们分别扩展到自动高度。第一次点击:“展开至文本跨度的全部高度”,第二次点击:“折叠回默认高度70像素”

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;
}

因此,在上面看起来非常简单,data-base我需要设置所需的固定高度的属性。的data-height我用来存储元素实际(动态)高度属性。

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);
    });

});

首先,我为第一个和第二个点击使用了clickToggle函数。第二个功能更重要:setAttr_height()所有.read-more元素的实际高度都在页面加载时在base-height属性中的。之后,通过jQuery css函数设置基本高度。

设置了两个属性后,我们现在可以平滑地在它们之间切换。仅data-base将更改为所需的(固定)高度,并将.read-more类切换为您自己的ID

大家都可以看到它在小提琴中运作

无需jQuery UI


1

如果您只想显示和隐藏一个div,那么此代码将使您可以使用jQuery动画。您可以让jQuery为您希望的大部分高度设置动画,也可以通过将动画设置为0px来欺骗动画。jQuery只需将jQuery设置的高度转换为自动即可。因此,.animate将style =“”添加到.css(height:auto)转换的元素中。

我看过的最干净的方法是将动画设置为您期望的高度,然后将其设置为自动,并且正确完成后看起来非常无缝。您甚至可以设置动画,超越您的期望,它将迅速恢复。以0的持续时间动画为0px只是将元素高度降至其自动高度。在人眼看来,它无论如何看起来都充满生气。请享用..

    jQuery("div").animate({
         height: "0px"/*or height of your choice*/
    }, {
         duration: 0,/*or speed of your choice*/
         queue: false, 
         specialEasing: {
             height: "easeInCirc"
        },
         complete: function() {
             jQuery(this).css({height:"auto"});
        }
    });

抱歉,我知道这是一篇过时的文章,但是我觉得这与仍然通过jQuery寻求此功能的用户有关。


0

我整理了一些东西,这些东西完全可以满足我的需求,而且看起来很棒。使用元素的scrollHeight可以获取元素在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>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.