正常设置折叠动画效果,展开height: auto,给定一个折叠height(例如height: 30px),然后使用transition动画效果实现,例如:
.div {
height: auto;
overflow: hidden;
transition: height .3s;
}
.div.collapse {
height: 30px;
}
写完会发现,transition动画效果并未生效。主要原因是设置height:auto,transition则需要具体的高度值。
常规会有以下几种解决方案(可根据具体场景使用):
1. 使用max-height方式
.div {
max-height: 120px;
overflow: hidden;
transition: max-height .3s;
}
.div.collapse {
max-height: 30px;
}
优点:使用简单
缺点:需要了解最大的高度值,这个值即要满足最大高度,又不能设置太大。对于一些动态渲染的部分,无法感知具体的高度,具体值,效果会偏差较大
2. 通过JS计算元素高度
2.1 首次渲染JS获取元素展开高度
.div {
overflow: hidden;
transition: height .3s;
}
// 缓存元素折叠高度
let minHeight = 30
// 缓存元素展开高度
let maxHeight = 0
const el = document.getElementById('div')
// 避免初始化折叠效果,无法获取最大高度
el.style.height = 'auto'
// 获取高度,并赋值给展开高度
maxHeight = el.getBoundingClientRect().height
// 如果是折叠效果
if (collapse) {
el.style.height = `${minHeight}px`
} else {
el.style.height = `${maxHeight}px`
}
优点: 精确获取元素高度
缺点: a. 元素及子元素不能更改高度;b. 如果刚进入是折叠效果,则需要先展开后计算出高度后再折叠,会有闪烁的效果
2.2 JS动态获取元素高度
.div {
overflow: hidden;
transition: height .3s;
}
const el = document.getElementById('div')
// 克隆当前元素
const cloneEl = el.cloneNode(true)
// 获取当前元素的宽度,避免全局添加,宽度不一致,高度计算偏差
const width = el.getBoundingClientRect().width
cloneEl.style = `width: ${width}px; height: initial; overflow: initial; visibility: hidden;`
// 全局渲染克隆元素
document.body.appendChild(cloneEl)
// 获取克隆元素的高度(与当前元素高度一致)
let height = cloneEl.getBoundingClientRect().height
// 移除克隆元素
document.body.removeChild(cloneEl)
if (!collapse && height > 30) height = 30
el.style.height = `${height}px`
优点:精确计算出元素的高度,可动态更改当前元素属性和添加更改子元素
缺点:需要克隆一个元素,会有渲染性能损耗(如果数量小和折叠不频繁,可忽略其性能问题)