使用transition-behavior: allow-discrete时,height反向过渡失效问题
问题根源
当元素被设为display: none时,它相当于从页面里“消失”了,浏览器不会保存它的任何布局状态。当你要展开它时,display先变回block,但这时候元素才刚被浏览器渲染出来,之前的height: 0状态根本没被记录,浏览器直接把高度拉到50px,自然就没过渡效果了。
transition-behavior: allow-discrete只能管收起的过程:先把高度缩到0,再隐藏元素。但展开时不行,因为元素隐藏的时候根本没布局数据,没法从0过渡到50px。
解决办法
要让展开收起都有平滑过渡,得手动控制样式变化的顺序:
- 收起:先让高度过渡到0,等动画结束再设
display: none - 展开:先把
display改回block,等浏览器把元素渲染出来,再让高度过渡到50px
修改后的代码如下:
JS 代码
const toggle = () => { document.querySelectorAll('.thing').forEach(el => { if (el.classList.contains('closed')) { // 展开:先取消高度收起状态,强制浏览器渲染元素,再取消隐藏 el.classList.remove('closed'); void el.offsetHeight; // 触发重绘,确保元素已显示 el.classList.remove('hidden'); } else { // 收起:先触发高度过渡,动画结束后隐藏元素 el.classList.add('closed'); el.addEventListener('transitionend', function end() { el.classList.add('hidden'); el.removeEventListener('transitionend', end); }, { once: true }); } }); } document.querySelector('button').addEventListener('click', toggle);
CSS 代码
.thing { overflow: hidden; height: 50px; transition: height 1s; outline: 1px solid blue; } .thing.closed { height: 0; } .thing.hidden { display: none; }
HTML 代码
<div class="thing"> I am thing </div> <div class="thing"> I am a discrete thing </div> <button>Toggle</button>
关键说明
- 用
transitionend事件等高度动画跑完再隐藏元素,不会打断过渡过程 - 展开时的
void el.offsetHeight是核心,它强制浏览器立即重绘元素,确保元素已经在页面布局中,此时取消隐藏,高度就能从0平滑过渡到50px - 去掉了
transition-behavior: allow-discrete,靠JS手动控制样式顺序,兼容性更强
内容的提问来源于stack exchange,提问作者DEfusion
相关产品推荐
相关产品推荐

