选择合适的方式,给用户更好的体验,多种方式实现 元素高度丝滑的从0-1显示出来。
能用 CSS 实现的动画,就不要采用 JS 去实现。
1、浏览器可以对CSS动画进行优化,其优化原理类似于requestAnimationFrame,会把每一帧的DOM操作都集中起来,在一次重绘和回流中去完成。一般来说频率为每秒60帧。
2、隐藏和不可见的dom不会进行重绘或回流,这样就会更少的使用CPU,GPU和内存使用量。
3、可以强制使用硬件加速;对于帧速不好的浏览器,css3可以做到自动降级,js则需要添加额外的代码。
对requestAnimationFrame有兴趣的可以看看作者的这个文。
提升用户体验之requestAnimationFrame实现前端动画_requestanimation 浏览器重绘-CSDN博客
1) 通过transition + height方式
transition只针对数值变化有效,所以 height:auto 不触发过渡动画,height:200px可触发动画 但该数值固定,无法满足不固定长度的情况。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.elA {width: 150px;height: 50px;background-color: #eee;}.elB {width: 300px;background-color: #5b734a;color: #ddd;height: 0;overflow: hidden;transition: 1s;position: absolute;}/* transition只针对数值变化有效,所以 height:auto 不触发过渡动画,height:200px可触发动画 但该数值固定,无法满足不固定长度的情况。*/.elA:hover+.elB {height: 200px;}</style>
</head><body><div class="elA">元素A</div><div class="elB">元素B<div class="inner">Lorem ipsum dolor sit amet consectetur adipisicing elit.<br>Architecto officiis repudiandae natus dolores quos porroeveniet eum temporibus aspernatur <br>commodi sapiente ab accusantiumdolorem nisi id nemo, obcaecati velit non.</div></div>
</body></html>
2) 通过transition + max-height方式
因无法确认显示内容最大高度,会导致设置高度过大,回缩时有延迟
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.elA {width: 150px;height: 50px;background-color: #eee;}.elB {width: 300px;background-color: #5b734a;color: #ddd;max-height: 0;overflow: hidden;transition: 1s;position: absolute;}/* 因无法确认显示内容最大高度,会导致设置高度过大,回缩时有延迟 */.elA:hover+.elB {max-height: 1000px;}</style>
</head><body><div class="elA">元素A</div><div class="elB">元素B<div class="inner">Lorem ipsum dolor sit amet consectetur adipisicing elit.<br>Architecto officiis repudiandae natus dolores quos porroeveniet eum temporibus aspernatur <br>commodi sapiente ab accusantiumdolorem nisi id nemo, obcaecati velit non.</div></div>
</body></html>
3) 通过transition + tranform:scale(0/1)
使用这种方式时,展示收回会出现一个压缩的过程
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.elA {width: 150px;height: 50px;background-color: #eee;}.elB {width: 300px;background-color: #5b734a;color: #ddd;transform-origin: center top;transform: scaleY(0);overflow: hidden;transition: 1s;position: absolute;}/* scale回缩时,会有展示出一个压缩的过程 */.elA:hover+.elB {transform: scaleY(1);}</style>
</head><body><div class="elA">元素A</div><div class="elB">元素B<div class="inner">Lorem ipsum dolor sit amet consectetur adipisicing elit.<br>Architecto officiis repudiandae natus dolores quos porroeveniet eum temporibus aspernatur <br>commodi sapiente ab accusantiumdolorem nisi id nemo, obcaecati velit non.</div></div></body></html>
4) 通过JS方式实现元素高度 丝滑展示
强制回流
1、(当DOM元素的大小、位置或可见性发生变化时,浏览器需要重新计算页面布局,这个过程就是回流。
这里通过计算的方式,实现回流。elB.getBoundingClientRect()
2、requestAnimationFrame的回调函数中进行DOM操作,如改变元素的样式、尺寸或位置,这些操作会排队等待浏览器的下一个重绘周期,触发回流。
requestAnimationFrame(cb)的方式触发回流。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.elA {width: 150px;height: 50px;background-color: #eee;}.elB {width: 300px;background-color: #5b734a;color: #ddd;overflow: hidden;transition: 1s;position: absolute;height: 0;}</style>
</head><body><div class="elA">元素A</div><div class="elB">元素B<div class="inner">Lorem ipsum dolor sit amet consectetur adipisicing elit.<br>Architecto officiis repudiandae natus dolores quos porroeveniet eum temporibus aspernatur <br>commodi sapiente ab accusantiumdolorem nisi id nemo, obcaecati velit non.</div></div><script>let elA = document.querySelector('.elA')let elB = document.querySelector('.elB')elA.onmouseenter = () => {// 先获取元素的自适应原始高度elB.style.height = 'auto'let h = elB.getBoundingClientRect().height// 回到最初的高度elB.style.height = 0// 代码到这里,页面会直接保持高度为0的状态,不会有动画。// 强制回流// 方式一、计算,(当DOM元素的大小、位置或可见性发生变化时,浏览器需要重新计算页面布局,这个过程就是回流。)// elB.getBoundingClientRect()// elB.style.height = h + 'px'// 方式二、在 requestAnimationFrame 的回调函数中进行DOM操作,如改变元素的样式、尺寸或位置,这些操作会排队等待浏览器的下一个重绘周期,触发回流。requestAnimationFrame(() => {elB.style.height = h + 'px'})}elA.onmouseleave = () => {elB.style.height = 0}</script>
</body></html>
如有不足,欢迎指导。
尽可能设想多种解决方案,在多种解决方案中选择一种代价较少的最优解决方案。