如何用CSS transition实现骨架屏淡出效果

作者:袖梨 2026-09-04

transition-opacity 必须在初始 class 中声明,否则 opacity 变化无动画;duration-300 需显式指定;淡出后须监听 transitionend 事件再移除 DOM 或设 visibility: hidden;骨架与真实内容需尺寸一致且同步过渡。

transition-opacity 必须写在初始 class 里,否则没动画

很多人给骨架屏加 opacity-0opacity-100 切换,结果元素瞬间消失——根本没过渡。原因不是 class 没切对,而是 transition-opacity 没出现在元素首次渲染的 class 列表中。

浏览器只会在「有 transition 声明的状态」下监听属性变化。如果 transition-opacity 是后来 JS 动态加上的,那之前 opacity 的任何变化(比如从 1 → 0)都不会被动画捕获。

  1. 正确写法:className="transition-opacity duration-300 opacity-100" —— transition-opacity 和初始 opacity-100 必须同时存在
  2. 错误写法:className={isVisible ? 'opacity-100' : 'opacity-0'} —— 缺少过渡声明,纯跳变
  3. duration-300 必须显式指定;transition-opacity 本身不含时长,只声明「哪个属性可过渡」

淡出后必须等 transitionend 再移除 DOM,不能靠 setTimeout

opacity 降到 0 后,元素仍占布局空间、能响应点击、影响 tab 导航。想真正清理,得等动画结束再执行 el.remove() 或状态更新。

硬写 setTimeout(() => el.remove(), 300) 非常危险:万一页面重排卡顿、CSS 重载、或用户调高系统动画速度,就会提前删 DOM,导致闪动或残留。

  1. 监听 transitionend 事件,且只响应 opacity 变化:if (e.propertyName === 'opacity' && getComputedStyle(el).opacity === '0')
  2. 避免被其他过渡干扰:比如容器同时有 heighttransform 过渡,要过滤掉
  3. React/Vue 中,不要在 useEffectwatch 里直接设 display: none —— 它会打断 opacity 过渡,变成硬切

别混用 visibility: hidden 和 transition-opacity

有人为了“保险”在 opacity-0 上叠加 visibility: hidden,结果动画直接消失——因为 visibility 生效是即时的,opacity 还没开始变,元素就不可见了。

visibility: hidden 不可过渡,它和 opacity 不是协同关系,而是互斥开关。真要用 visibility,只能放在 transition 结束后作为 cleanup 步骤。

  1. 淡出阶段:只靠 opacity + transition 控制视觉渐隐
  2. 淡出完成:在 transitionend 回调里设 visibility: hidden 或直接 remove()
  3. 绝对不要写 opacity-0 visibility-hidden 同时生效 —— 这会让浏览器放弃 opacity 动画

骨架屏淡出时,真实内容要同步入场,避免布局抖动

常见翻车:骨架层刚 opacity: 0,真实图片就立刻加载并撑开容器,页面猛地一跳。这不是 CSS 问题,而是 DOM 层级和样式没对齐。

关键不是“怎么让骨架走”,而是“怎么让内容稳着进”。真实内容必须和骨架层尺寸完全一致,且初始不可见。

  1. 真实 <img> 要套在和骨架同尺寸的容器里,设 position: absolute 盖住骨架
  2. 初始状态:opacity: 0 + visibility: hidden,等 onload 后只加一个 is-loaded
  3. .is-loaded 里只写 opacity: 1 + visibility: visible,靠同一组 transition: opacity 0.3s ease 衔接
  4. 骨架层如果是 ::before,记得在 .is-loaded::before 里加 display: none
过渡类必须从首帧就存在,动画触发时机取决于 DOM 渲染起点,而不是你什么时候想起来加 class。骨架屏的淡出效果,本质是两套状态的精准咬合:视觉退场、内容进场、DOM 清理,三者缺一不可。

相关文章

精彩推荐