Анімаційний елемент до автоматичної висоти за допомогою jQuery


171

Я хочу , щоб анімувати <div>від 200pxдо autoвисоти. Я не можу, здається, змусити його працювати. Хтось знає як?

Ось код:

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

14
Ви повинні відзначити найкращу відповідь як прийняту.
kleinfreund


@IanMackinnon на це питання, безумовно, є кращі відповіді. Я закрив це питання як дублікат цього.
Привид

Відповіді:


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, які показують елементи, на які ви посилаєтесь.
Девід Тан

21
Це працює, але я додав зворотний виклик, який відновлює поведінку автоматичного зростання елементу .animated({height: autoHeight}, 1000, function(){ el.height('auto'); });
rg89

Будьте уважні до встановлення фіксованої висоти на чуйних конструкціях. Це перетворюється на безлад, якщо користувач змінює розмір екрана. Найкраще встановити висоту на "авто", коли анімація завершена.
Джонатан Тонге

4
Це може викликати FOUC. Користувач може побачити, як елемент перестрибує в повний зріст на частку секунди, перш ніж анімувати.
Dingredient

1
Ви можете попередити FOUC ("спалах невідомого вмісту"), спочатку даючи елемент opacity: 0; position: absolute;під час його вимірювання та видаляючи ті, щойно ви закінчите.
JacobEvelyn

194

IMO - це найчистіше і найпростіше рішення:

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

Пояснення: DOM вже знає з початкового відображення, який розмір матиме розширений div, коли буде встановлено автоматичну висоту. Це властивість зберігається у вузлі DOM як scrollHeight. Нам просто потрібно отримати елемент DOM з елемента jQuery, зателефонувавши, get(0)і тоді ми зможемо отримати доступ до ресурсу.

Додавання функції зворотного дзвінка для автоматичного встановлення висоти дозволяє отримати більшу реакцію, коли анімація завершена (кредитна криза-вілліами ):

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

2
Дивовижний! За даними developer.mozilla.org/en-US/docs/Web/API/Element.scrollHeight він навіть підтримується в IE8, порівняно з clientHeight, який, здається, не підтримується: developer.mozilla.org/en-US/docs/Web/ API / Element.clientHeight
Sven

1
Поле за визначенням моделі коробки не є частиною висоти об'єкта. Ви завжди можете додати маржу самостійно.
Ліквіно

22
Це має бути прийнятою відповіддю, оскільки вона найкраще працює без мерехтіння і справді справляється добре
Ейніус,

7
Я також думаю, що це найкраще рішення. Я б додав до нього функцію зворотного дзвінка, щоб встановити висоту для автоматичного для більшої чуйності. $('#first').animate({ height: $('#first').get(0).scrollHeight }, 1000, function() { $(this).height('auto'); });
Кріс Вільямс

1
Ого, це супер елегантно. Він також працює з scrollWidthанімацією по ширині.
nils

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
Цей онлайнер не просто зрозуміти, можливо, написання декількох рядків допоможе іншим трохи краще.
Яап

Це найкраще рішення, оскільки висота авто може змінитися, якщо користувач регулює розмір вікна. Дивіться наступне: // анімує висоту функції фільтрів toggleSlider () {if ($ ('# filters'). Height ()! = 0) {$ ('# filters'). Animete ({height: '0 '}); } else {var $ selector = $ ('# фільтри'); $ selector .data ('oHeight', $ selector.height ()) .css ('height', 'auto') .data ('nHeight', $ selector.height ()) .height ($ selector.data (' oHeight ')) .animate ({висота: $ selector.data (' nHeight ')}, 400); }; console.log ('agg'); }
Рікі

Працює над тим, щоб діва відкрилася, але не оживляла більше 400 мс. Можливо, у мене щось інше встановлено інакше, але це просто відкривається мить.
ntgCleaner

Працює, але це встановлює heightфіксовану величину (наприклад, 122 пікселів). Мій елемент через деякий час змінив висоту, тому мені довелося замінити аргумент тривалості (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


1
Слід зазначити, що для цього потрібен плагін Jquery UI, тоді як початкове питання стосувалося лише jquery. Але якщо ви використовуєте інтерфейс Jquery, він працює.
користувач56reinstatemonica8

4
ви також можете використовувати $ (this) .toggleClass ('max', 250); замість використання заяви if
Антуан Їжак

1
чому ви включаєте друге значення з .addClassі .removeClass?
чаша0сту


7

Ви завжди можете обернути дочірні елементи #first і зберегти висоту висоти обгортки як змінну. Це може бути не найкрасивішою чи найефективнішою відповіддю, але це робить трюк.

Ось загадка, де я включив скидання.

але для ваших цілей, ось м'ясо та картопля:

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

Використовуйте slideDown та slideUp

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

1
Це не вирішує висоту: автоматична функція, оскільки slideUp повністю згортає діл.
Яап

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, тому ви можете використовувати його для більш ніж просто анімації.
Стен Джордж

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

2

Можливо, ваші селектори не відповідають. Чи має ваш елемент ідентифікатор 'first', або це перший елемент у кожному div?

Більш безпечним рішенням буде використання "цього":

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

1
Ага. Ну, схоже, ви знайшли рішення. Для безпеки я все-таки використовую $(this)всередині вашого обробника кліків.
EMMERICH

10
animate({height: 'auto'})не має жодного ефекту. Принаймні, не з jQuery 1.6.4.
Яніс Елмеріс

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

це не буде працювати, ваша висота вару просто доступна всередині готової функції.
мео

визначте висоту перед функцією готовості та використовуйте лише висоту, ніж висота var .. таким чином це може працювати даніель
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)();
        });
};

Будь-який із використаних параметрів можна опустити або встановити на нуль, щоб прийняти значення за замовчуванням. Я використовував параметри:

  • зростанняTo: Якщо ви хочете змінити всі обчислення та встановити висоту 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);
    }
});

По суті такий же, як один вкладиш Геттлера, але простіший для розуміння.
Тимофій Гроот

1

Мені потрібна ця функціональність для декількох читати більше областей на одній сторінці, впроваджуючи це в короткий код Wordpress, я зіткнувся з тією ж проблемою.

Технічно спроектований дизайн всіх проміжок часу на сторінці має фіксовану висоту. І я хотів мати можливість розширити їх окремо до автоматичної висоти за допомогою перемикача. Перший клік: 'розгорнути до повної висоти текстового діапазону', другий клацати: 'повернути до висоти 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;
}

Отже, над цим виглядає дуже простий 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атрибуті. Після цього встановлюється висота основи через функцію css jquery.

За допомогою обох наших атрибутів ми тепер можемо плавно перемикатися між ними. Змініть лише data-baseбажану (фіксовану) висоту та переключіть клас .read-more на власний ідентифікатор

Ви можете бачити, як це працює у скрипковому ПІДТВОРЕННІ

Не потрібен інтерфейс jQuery


1

Якщо все, що ви хочете, - це показати та приховати сказати дів, тоді цей код дозволить вам використовувати jQuery animate. Ви можете мати jQuery анімувати більшу частину бажаної висоти, або ви можете обдурити анімацію, анімувавши до 0px. jQuery просто потрібна висота, встановлена ​​jQuery, щоб перетворити його в автоматичний. Отже .animate додає стиль = "" до елемента, який перетворює .css (висота: авто).

Найчистіший спосіб, який я бачив у цій роботі, - це анімувати приблизно очікувану висоту, тоді нехай вона встановлюється автоматично, і вона може виглядати дуже безшовно, якщо виконати правильно. Ви навіть можете оживити минуле того, що очікуєте, і це відкинеться назад. Анімація до 0px тривалістю 0 просто знижує висоту елемента до його автоматичної висоти. Для людського ока це все одно виглядає оживленим. Насолоджуйтесь ..

    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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.