如何使用jQuery将元素动画化为其自然高度

时间:2009-09-02 19:43:32

标签: javascript jquery css

我正在试图让一个元素动画到它的“自然”高度 - 即它有height: auto;时的高度。

我想出了这个:

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

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

有更好的方法吗?感觉有点像黑客。

编辑: 这是一个完整的脚本供任何想要测试的人使用。

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

9 个答案:

答案 0 :(得分:11)

我允许自己回答这个帖子,即使很久以前已经回答了这个问题,因为它只是帮助了我。

事实上,我不明白第一个答案:为什么打开一个半封闭的元素来获得它的高度,然后再关闭它?

一开始,你隐藏了元素,只显示它的一部分,对吧?使用javascript,最好的方式(我相信)是这样做的。因此,当您隐藏元素时,只需将orig高度保存在var中,这样您就不必隐藏(onready)-show-save height-hide以便能够切换元素的可见性。

看看我做了什么,它完美无缺:

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

在这里,当您调用切换功能时,您可以知道原始元素高度是多少而不会四处游荡。

我写得很快,希望将来可以帮助某人。

答案 1 :(得分:10)

我找到的最简单的解决方案是简单地用一个高度有限的div包装内容元素并设置为overflow:hidden。这会将内部内容元素截断为包装div的高度。当用户点击,悬停等以显示内容元素的完整高度时 - 只需将包装div设置为内部内容div的高度。

答案 2 :(得分:6)

我可以建议一个同样黑客的解决方案......克隆元素,将其放在视野之外,然后获得它的高度......然后删除它并为原始动画制作动画。

除此之外,您还可以使用$ .slideUp()和$ .slideDown():

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

如果您需要保留1px行,可以将其应用于父元素:

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

并在.toggleMe div上应用slidingUp / Down。

答案 3 :(得分:1)

如果可以的话,我也想加入这个旧帖子,万一我的解决方案可以帮助任何人。我的具体情况是这样的:我有一些设置了最大高度值的div,它们将它们限制为三行高,当用户将鼠标移过它们时,我希望它们扩展到它们的自然高度;当鼠标光标离开div时,我希望它们缩小回到剪裁的最大三行高。我需要使用CSS max-height属性而不是height,因为我有一些div只包含一行或两行文本,我不希望它们不必要地高。

我在这个帖子中尝试了很多解决方案,而对我有用的解决方案是Jonathan Sampson建议的涉及克隆元素的“hackish建议”。我将他的想法翻译成以下代码。请随时提出改进建议。

将函数委托给父元素以处理通过Ajax调用创建的div。 div.overflow_expandable类具有以下声明:{ 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');
});

答案 4 :(得分:1)

发现这篇文章并最终使用Greg的原始1px建议 - 效果很好!

刚刚向animate函数添加了一个回调,在动画结束时将元素的高度设置为'auto'(在我的情况下,该特定元素的内容可能会更改并且更大)。

答案 5 :(得分:0)

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

一旦完成滑动,就应该将p标签的高度设置为1px。

答案 6 :(得分:0)

这对我有用。

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

答案 7 :(得分:0)

我的解决方案是在关闭按钮的data属性中存储容器的原始大小(如果您不使用相同的按钮也可以再次显示容器本身,也可以存储在容器本身中)容器):

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

答案 8 :(得分:0)

我想指向this answer,建议将高度设置为&#34;显示&#34;使用animate()函数。我不得不编辑我的&#34; slideUp&#34;风格动画使用高度:&#34;隐藏&#34;与之合作。