概述
css里面,要想元素从一个状态过渡到另外一个状态,就需要有数值的变化,比如opacity、transform、background-color等等,但是我们可能经常遇到的一个问题就是,一个元素的高度是自适应的,也就是height:auto,然后我们想要过渡到0,这样我们设置transition后是没法实现的,因为auto到0不是两个具体值之间的过程,因此这里总结一起高度自适应过渡的处理方式。
效果
实现
关键requestAnimationFrame
window.requestAnimationFrame()
告诉浏览器------你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。出了这个方法之外,setTimeout也是可以的,但是更加推荐requestAnimationFrame方法。
注意点
- 首先我们我们通过动态获取需要过渡元素的高度,然后再动态设置过渡元素的高度,这样就有了两个具体数值之间的产生,因此transition就可以生效。
- js动态设置高度的时候,高度那块不能同步更改,因为js执行是同步的,最终渲染的时候,是最后设置的那个值。
- 动画执行完毕,需要移除我们动态设置的高度,因此这样产生的副作用可能影响后续动态追加的元素,这样就会产生无法自适应高度的bug.
代码
``
js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.box {
width: 300px;
margin: auto;
overflow: hidden;
background-color: palegreen;
transition: 0.3s;
}
.box-item {
line-height: 40px;
text-align: center;
}
</style>
</head>
<body>
<button class="operate-button">折叠</button>
<button class="add-button">追加</button>
<div class="box">
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
<div class="box-item">this is a text this is a text</div>
</div>
<script>
let operateButton = document.querySelector(".operate-button");
let addButton = document.querySelector(".add-button");
let box = document.querySelector(".box");
let tag = false;
// 监听过渡执行完毕
box.addEventListener("transitionend", () => {
console.log(tag);
if (!tag) {
box.style.removeProperty("height");
}
});
operateButton.addEventListener("click", () => {
if (tag) {
box.style.height = "auto";
const height = box.offsetHeight;
box.style.height = 0;
//下次重绘(下一帧)执行
requestAnimationFrame(() => {
box.style.height = height + "px";
});
operateButton.textContent = "折叠";
} else {
const height = box.offsetHeight;
box.style.height = height + "px";
//下次(下一帧)重绘执行
requestAnimationFrame(() => {
box.style.height = 0;
});
operateButton.textContent = "展开";
}
tag = !tag;
});
addButton.addEventListener("click", () => {
const cloneLiItem = document.querySelector(".box-item").cloneNode(true);
box.appendChild(cloneLiItem);
});
</script>
</body>
</html>