transition 不能直接作用于 opacity 的常见误解在于未显式改变 opacity 值,必须有明确起始(如 opacity: 1)和结束值(如 opacity: 0.4)切换才能触发过渡。
很多人写了 transition: opacity 0.3s 之后发现没有效果,原因并非语法错误,而是 opacity 自身的值没有变化——例如元素初始状态就是 opacity: 1,同时又未在:hover或class切换时明确修改该值,因此不会触发过渡。
需要把握的关键是:transition 只会响应“属性值变化”,并不负责“初始化动画”。起始值和结束值必须发生明确切换,比如从 opacity: 1 → opacity: 0.4。
opacity(不要使用浏览器默认值)class 切换或由JS修改 style.opacity 以触发数值变化opacity: inherit 或者 opacity: unset,因为它们不能参与过渡计算用纯CSS制作透明度过渡时,最常采用的是 :hover,但需要检查父容器有没有遮挡,以及是否设置了 pointer-events: none,否则伪类不会生效。
下面是一种可靠的写法:
立即学习“前端免费学习笔记(深入)”;
.fade-box { opacity: 1; transition: opacity 0.25s ease-in-out;}.fade-box:hover { opacity: 0.6;}
opacity,即便它与默认值相同(1)ease-in-out 相比之下 linear 更为自然,不过若需精准控制节奏,可以使用 cubic-bezier(0.34, 1.56, 0.64, 1)
touch-action: manipulation 以免点击延迟造成过渡卡顿有人希望“淡出后彻底隐藏”,便采用这种写法:
.box { opacity: 1; visibility: visible; transition: opacity 0.3s;}.box.hidden { opacity: 0; visibility: hidden;}
随之而来的问题是:visibility 不能进行过渡,所以元素会在 opacity 动画结束的一瞬间突然消失,造成视觉断层。更严重的是,如果JS在动画尚未结束时便添加了 .hidden,opacity ,还未降至0就会被强制截断。
opacity + pointer-events: none(禁用交互)+ will-change: opacity(提示渲染优化)visibility,应该在 transitionend 事件中再设置 visibility: hidden,这样通过JS控制才可靠opacity: 0 相关元素依然会占用布局、可以获得焦点并能响应事件,这一点经常被忽略低于 0.12s 的过渡几乎无法被人眼察觉,设置后等同于没有渐变;高于 0.4s 则容易让用户感到“卡顿”或“响应迟缓”,按钮反馈等高频交互中的感受尤其明显。
0.18s–0.25s,模态框淡入建议使用 0.3s(配合transform更加稳定)transition,否则会形成重绘压力,在低配安卓机上尤为明显prefers-reduced-motion 媒体查询进行兜底:@media (prefers-reduced-motion: reduce) { * { transition-duration: 0.01ms !important; } }
opacity过渡虽然看似简单,但要在各种设备和交互路径中稳定运行,必须理清起始状态、触发时机、隐藏逻辑和动效节奏这四个方面。任何一点缺失,都可能让用户遇到闪、卡、断或误触。