前端高度变化实现过渡动画
一、height二、max-height三、transform四、grid五、JavaScript可能会问到的问题
一、height
前提:已知初始高度与最终高度。如果有这个前提,那么这个动画是最好实现的了。<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>height</title><style>.select {/* 初始高度 */height: 0;overflow: hidden;background-color: red;/* 过度动画持续1s */transition: all 1s;}button:hover+.select {/* 最终高度 */height: 110px;background-color: pink;}</style></head><body><button>hover</button><div class="select"><div>前提:已知初始高度与最终高度。</div><div>如果有这个前提,那么这个动画是最好实现的了。</div><div>3</div><div>4</div></div></body></html>
二、max-height
利用最大高度实现过度动画。但是有缺陷,如果最大高度大于需要的高度,就会有明显的延迟。(相当于设置了初始高度与最终高度)<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>max-height</title><style>.select {/* 初始最大高度 */max-height: 0;overflow: hidden;background-color: red;/* 过度动画持续1s */transition: all 1s;}button:hover+.select {/* 最终最大高度 */max-height: 110px;/* 缺陷将下面代码注释去掉,你就知道了。*//* max-height: 1110px; */background-color: pink;}</style></head><body><button>hover</button><div class="select"><div>利用最大高度实现过度动画。</div><div>但是有缺陷,如果最大高度大于需要的高度,就会有明显的延迟。(相当于设置了初始高度与最终高度)</div><div>3</div><div>4</div></div></body></html>
三、transform
利用的就是放大,缩小。这个方法是用css实现最简单的方法。<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>transform</title><style>.select {/* 缩小到0 */transform: scaleY(0);transform-origin: center top;overflow: hidden;background-color: red;/* 过度动画持续1s */transition: all 1s;}button:hover+.select {/* 恢复到原本大小 */transform: scaleY(1);background-color: pink;}</style></head><body><button>hover</button><div class="select"><div>利用的就是放大,缩小。</div><div>这个方法是用css实现最简单的方法。</div><div>3</div><div>4</div></div></body></html>
四、grid
利用的是栅格布局缺陷:就是很新的布局,很多老浏览器不支持;并且Safari浏览器不支持grid动画。<!-- 参考资料: https://juejin.cn/post/7196843994030342200 --><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>grid</title><style>.parent {/* 将父设置为grid布局 */display: grid;/* 设置子高度为0fr */grid-template-rows: 0fr;overflow: hidden;transition: all 1s;background-color: red;}/* 必须将子元素的最小高度设置一下,不然没有效果,因为0fr选取的就是文字自动撑开的高度 */.parent div {min-height: 0;}button:hover+.parent {/* 设置子高度为1fr */grid-template-rows: 1fr;background-color: pink;}</style></head><body><button>hover</button><div class="parent"><div class="select"><div>利用的是栅格布局</div><div>缺陷:就是很新的布局,很多老浏览器不支持;并且Safari浏览器不支持grid动画。</div><div>3</div><div>4</div></div></div></body></html>
五、JavaScript
最终实现走的还是height,只是通过JavaScript来获取已知初始高度与最终高度来实现动画。缺陷:效率问题,并且实现起来最复杂。<!-- 参考资料-深入理解浏览器的重绘与重排: https://zhuanlan.zhihu.com/p/148825597 --><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>JavaScript</title><style>.select {--origin-height: 0;/* 初始高度 */height: var(--origin-height);overflow: hidden;/* 反正动画一直在,可以写好动画 */transition: height 1s;background-color: pink;}</style></head><body><button>hover</button><div class="select"><div>最终实现走的还是height,只是通过JavaScript来获取已知初始高度与最终高度来实现动画。</div><div>缺陷:效率问题,并且实现起来最复杂。</div><div>3</div><div>4</div></div><script>// 获取按钮domconst button = document.querySelector('button')// 获取列表domconst select = document.querySelector('.select')// 获取初始高度const originHeight = getComputedStyle(select).getPropertyValue('--origin-height')// 类似与css中hover:onmouseenter、onmouseleave// 进入button.onmouseenter = () => {// 自适应高度select.style.height = 'auto'// 这个时候,通过select.offsetHeight来重排获取最新确定的数值高度const height = select.offsetHeight// 恢复最开始的状态select.style.height = originHeight// 通过select.offsetHeight来页面重排,从而确保页面的过渡// 如果去掉这句话,那么动画就不会生效select.offsetHeight// 最终确定高度select.style.height = height + 'px'}// 离开button.onmouseleave = () => {/* 恢复初始高度 */select.style.height = originHeight}</script></body></html>
可能会问到的问题
为什么高度设置成auto不行?height: auto;auto不是数值,所以动画没有效果,而需要产生动画效果,必须是数值单位。相当于必须告诉transition初始是多少,最终是多少;是一个确切的值或者是有计量单位就可以。