正常设置折叠动画效果,展开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 = 0const 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().widthcloneEl.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 = 30el.style.height = `${height}px`
优点:精确计算出元素的高度,可动态更改当前元素属性和添加更改子元素
缺点:需要克隆一个元素,会有渲染性能损耗(如果数量小和折叠不频繁,可忽略其性能问题)