先记住一个核心结论:用 `transition` 配合 class 切换,是实现状态驱动显隐动画最干净、最可控的方案。不少同学一上来就想用 `@keyframes` 来做开关类动画,但那个更适合循环或复杂运动序列,而“点一下,出来;再点一下,消失”这种高频交互,`transition` 是唯一合理的
transition 配合 class 切换实现状态驱动显隐动画纯CSS动画本身并不响应JS的状态变化——它只是舞者,不是指挥。你必须有class来充当那个“信号灯”,告诉CSS“现在该动了”。所以,所谓“状态驱动”,其实就是靠JS动态给元素增减class,触发transition。
长期稳定更新的攒劲资源: >>>点此立即查看<<<
关键在于组合里的“化学反应”:
opacity: 0 + visibility: hidden:最经典,适合纯粹的淡入淡出,元素本身不占位,高度不变。max-height: 0 + overflow: hidden:适合折叠/展开,视觉效果明显,但要小心max-height设得太大会造成延迟感,通常设成比实际内容高度略大就行。transition 写在“稳定态”的 class 上,而不是“切换态”。什么意思?比如 .panel 默认可见,那过渡属性就放在 .panel 里;如果反过来,把过渡写在 .is-hidden 上,第一次进入页面时会直接没有动画,因为浏览器没得过渡可走。.panel {
opacity: 1;
visibility: visible;
transition: opacity 0.2s ease, visibility 0.2s ease;
}
.panel.is-hidden {
opacity: 0;
visibility: hidden;
}
@if 控制不同状态下的动画参数首先要明确:SCSS的 @if 是编译时行为,不是运行时。它没法读懂JS变量的当前值,它只认得你写在SCSS文件里的变量字面量。所以别指望用 @if $is-active 来直接响应JS状态——SCSS编译完以后这些东西就都蒸发掉了。
那么它到底有什么用?答案是:按组件变体生成不同的动效规则。比如,你的页面上有两种下拉菜单:一种是快速弹出(.dropdown--fast),一种是慢速平滑(.dropdown--smooth)。这时候用 @if 配合 @mixin 封装就很顺手。
@mixin,再通过 @if 分支注入不同的时长和缓动函数。feature-exists() 这类编译期函数。@mixin fade-transition($duration: 0.2s, $easing: ease) {
transition: opacity $duration $easing, visibility $duration $easing;
}
.card {
@include fade-transition();
}
.card.card--slow {
@include fade-transition(0.4s, ease-out);
}
一个很常见的场景:用户狂点切换按钮,JS快速连续 toggle class,结果元素卡在一半透明度,或者动画明显跳跃。根本原因在于浏览器没来得及重新计算布局(reflow)就又改了一次样式。
解决办法有几个:
el.offsetHeight 或 getComputedStyle(el).opacity——但记住,这是个性能杀手,能不用就不用。transitionend 事件做下一步,而不是依赖 setTimeout。为什么?因为 setTimeout 的时间不一定和过渡时长精确对齐。transitionend 在 opacity 和 visibility 上的触发次数不一样——后者根本不触发。如果你同时过渡这两个属性,transitionend 只会因 opacity 触发一次,别漏判了。显隐动画后面通常跟着DOM操作——比如隐藏完了直接 el.remove()。很多人习惯用 setTimeout 来做这件事,但很容易出问题:时间设短了动画还没做完就删了元素,设长了又让页面有卡顿感。
正确做法只有一个:监听 transitionend,并且做好过滤。
event.propertyName === 'opacity' 判断动画是否真正结束。transitionend 会触发多次,不加过滤的话清理逻辑会重复执行,风险很大。{ once: true } 让监听器自动解绑,省得手动 removeEventListener,防止内存泄漏。el.addEventListener('transitionend', (e) => {
if (e.propertyName === 'opacity' && e.target === el) {
el.remove();
}
}, { once: true });
坦白说,实际项目中最容易被忽略的,是把动画控制逻辑分散在JS、SCSS、CSS三处,结果要调整一个动画时长,得翻三份文件。一个更好的做法是:把所有动效参数(时长、缓动、延迟)抽成CSS自定义属性,JS通过 el.style.setProperty('--anim-duration', '0.3s') 动态注入,SCSS用 var(--anim-duration) 读取——这样控制点就统一在一个地方了。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述