使用classList.toggle切换类时CSS Transition过渡不生效如何解决
classList.toggle 不会导致过渡丢失,它仅修改元素的class属性值,不会清除元素上绑定的CSS过渡规则,你的问题和这个API无关。
问题根本原因
你的CSS中同时修改了两个属性:
max-height:数值类属性,支持平滑过渡white-space:枚举类属性,不支持平滑过渡,修改后会即时生效
当你点击元素添加open类时,white-space: normal会瞬间让原本不换行的文本换行,元素实际高度直接跳到最终值,max-height的过渡效果被即时的高度跳变完全覆盖,视觉上就表现为没有触发过渡。
修复方案
第一步:调整CSS,仅针对可过渡属性设置过渡规则
不要用all作为过渡属性,明确只过渡max-height,避免不可过渡属性影响效果:
.toggleMe { background: #e3e3e3; max-height: 1.3rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 100%; transition: max-height ease 2s; -moz-transition: max-height ease 2s; /* Firefox 4 */ -webkit-transition: max-height ease 2s; /* Safari和Chrome */ -o-transition: max-height ease 2s; /* Opera */ -ms-transition: max-height ease 2s; /* IE10 */ } .toggleMe.open { max-height: 300px; /* 建议设置为略大于最大内容高度的数值,不要用过大的999px,避免过渡速度不均匀 */ /* white-space改为用JS动态控制,不要写在这里 */ }
第二步:调整JS逻辑,延迟修改white-space属性
监听过渡完成事件,等max-height的展开过渡结束后再修改white-space,收起时先改回white-space: nowrap再触发过渡:
document.querySelectorAll('.toggleMe').forEach(function (el) { el.onclick = function (e) { // 用currentTarget避免点击子元素时target指向错误 const target = e.currentTarget; const isOpen = target.classList.contains('open'); if (isOpen) { // 收起逻辑:先改回不换行,再触发高度收缩过渡 target.style.whiteSpace = 'nowrap'; requestAnimationFrame(() => { target.classList.remove('open'); }); } else { // 展开逻辑:先触发高度展开过渡,过渡结束后再改为允许换行 target.classList.add('open'); const handleTransitionEnd = () => { target.style.whiteSpace = 'normal'; target.removeEventListener('transitionend', handleTransitionEnd); }; target.addEventListener('transitionend', handleTransitionEnd); } } });
额外优化建议
如果对收起时的省略号显示没有强需求,也可以直接把white-space: normal固定写在.toggleMe的基础样式里,去掉所有和white-space相关的JS逻辑,只靠max-height和overflow: hidden控制显示,代码更简单,只是默认状态下不会显示单行省略号。
内容的提问来源于stack exchange,提问作者SweetTomato
相关产品推荐
相关产品推荐

