javascript - 用纯 JS 动画最大高度?

标签 javascript html css

我想为 div 的高度设置动画。这通常在 CSS 中通过为 max-height 属性设置动画来完成。

但是我需要在 JS 中执行此操作。 div 填充了经常变化的动态内容,因此无法提前知道实际高度。

这是一个 jsfiddle:https://jsfiddle.net/vpknxuk8/

var box = document.getElementById("box");
var button = document.getElementById("button");
var expanded = true;

button.addEventListener('click', function() {
    if (expanded) {
        box.style.maxHeight = 0;
        expanded = false;
    } else {
        box.style.maxHeight = "";
        expanded = true;
    }
});
#box {
  margin-top: 20px;
  border: 1px solid black;
  background-color: #4f88ff;
  width: 200px;
  transition: max-height 0.25s linear;
  overflow: hidden;
}
<button id="button">Click</button>

<div id="box">
  Hello World<br>
  This is dynamic content<br>
  The actual height won't be known ahead of time
</div>

盒子应该在高度 0 和它的默认高度之间转换,但由于某些原因它没有动画。

StackOverflow 上此问题的唯一其他版本与纯 CSS 解决方案或 jQuery 解决方案有关。

最佳答案

不要使用max-height ...好吧,除非你想采用CSS-only 草率的解决方案会产生延迟间隙问题 - ...这就是为什么你首先重新使用 JS,希望如此

因此,请改用heighttransition: height

function slidetoggle() {

  document.querySelectorAll(this.getAttribute('data-slidetoggle')).forEach(el => {
    const ch = el.clientHeight,
      sh = el.scrollHeight,
      isCollapsed = !ch,
      noHeightSet = !el.style.height;

    el.style.height = (isCollapsed || noHeightSet ? sh : 0) + "px";
    if (noHeightSet) return slidetoggle.call(this);
  });
}


document.querySelectorAll("[data-slidetoggle]").forEach(el => el.addEventListener('click', slidetoggle));
#box1,
#box2 {
  overflow: hidden;
  margin-bottom: 20px;
  background-color: #4f88ff;
  width: 200px;
  transition: height 0.5s;
}
<button data-slidetoggle="#box1">Toggle Box 1</button>

<div id="box1">
  Hello World<br> This is dynamic content<br> The actual height won't be<br> known ahead of time
</div>

<button data-slidetoggle="#box2">Toggle Box 2</button>


<div id="box2">
  Hello World<br> This is dynamic content<br> The actual height won't be<br> known ahead of time<br> bla
  <br> bla
  <br> bla
</div>

提示:如果您需要填充,我的建议是将您的内容包装到另一个子框中 - 使用填充。

上面的代码是概念性的和最小的 - 有很大的改进空间,但希望你明白了。

为什么要用上面的解释,为什么不使用下面的:

如果我们不设置初始高度,CSS height-transition 将无法工作。
所以基本上是在点击时——如果这样的高度不存在,我们需要通过 JS 来设置它。
设置了这样的高度后,转换仍然无法工作,因为浏览器没有时间计算这样的元素的盒子模型 - 到转换自:

// (INVALID DEMO) 
//
// Say the element is expanded.
// We need a height to transition-from
el.height = calculatedHeight +"px";  // set CSS height to the calculated value
// Transition to 0px height....
el.height = 0 +"px";
// NO DEAL. our element just snapped to 0 without transition

因此我们需要驻留在某种回调
一种常见的(但草率的方式)是使用 setTimeout() 回调

// (INVALID DEMO) 
//
// Say the element is expanded.
// We need a height to transition-from
el.height = calculatedHeight +"px";  // set CSS height to the calculated value
// Transition to 0px height giving the browser some ready-state hack
setTimeout(function() {
    // Eventually the box model will be calculated 
    el.height = 0 +"px";
}, 0);   // <<< PROBLEM: Should we use 0 ? 10? 100? 1000? 
// and our element beautifully transitioned to 0 height.
// Eventually :(

关于javascript - 用纯 JS 动画最大高度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44467909/

相关文章:

javascript - 访问 JAX-RS RESTful API

javascript - 使用html打开大写的android和ios键盘

iphone - @font-face 在 iPhone 版本的 Safari 上已弃用。我有什么选择?

html - 设置与 CSS 边框不冲突的表格边框

javascript - 在javascript中查找特定单词(正则表达式)中的字符类型

javascript - ng2 初始化 DOM 属性一次并删除更改检测

javascript - AngularJS错误处理: show errors based on array of errors

javascript - 如何根据用户指定的时间填充一个100%的进度条

javascript - 使用 AngularJS 预选择一个选择项不起作用

javascript - 在输入标签上使用 keyup 事件的 JS 搜索