最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何用CSS transition实现骨架屏淡出效果
时间:2026-09-04 20:42:47 编辑:袖梨 来源:一聚教程网
transition-opacity 必须在初始 class 中声明,否则 opacity 变化无动画;duration-300 需显式指定;淡出后须监听 transitionend 事件再移除 DOM 或设 visibility: hidden;骨架与真实内容需尺寸一致且同步过渡。
transition-opacity 必须写在初始 class 里,否则没动画
很多人给骨架屏加 opacity-0 和 opacity-100 切换,结果元素瞬间消失——根本没过渡。原因不是 class 没切对,而是 transition-opacity 没出现在元素首次渲染的 class 列表中。
浏览器只会在「有 transition 声明的状态」下监听属性变化。如果 transition-opacity 是后来 JS 动态加上的,那之前 opacity 的任何变化(比如从 1 → 0)都不会被动画捕获。
- 正确写法:
className="transition-opacity duration-300 opacity-100"——transition-opacity和初始opacity-100必须同时存在 - 错误写法:
className={isVisible ? 'opacity-100' : 'opacity-0'}—— 缺少过渡声明,纯跳变 -
duration-300必须显式指定;transition-opacity本身不含时长,只声明「哪个属性可过渡」
淡出后必须等 transitionend 再移除 DOM,不能靠 setTimeout
opacity 降到 0 后,元素仍占布局空间、能响应点击、影响 tab 导航。想真正清理,得等动画结束再执行 el.remove() 或状态更新。
硬写 setTimeout(() => el.remove(), 300) 非常危险:万一页面重排卡顿、CSS 重载、或用户调高系统动画速度,就会提前删 DOM,导致闪动或残留。
- 监听
transitionend事件,且只响应 opacity 变化:if (e.propertyName === 'opacity' && getComputedStyle(el).opacity === '0') - 避免被其他过渡干扰:比如容器同时有
height或transform过渡,要过滤掉 - React/Vue 中,不要在
useEffect或watch里直接设display: none—— 它会打断 opacity 过渡,变成硬切
别混用 visibility: hidden 和 transition-opacity
有人为了“保险”在 opacity-0 上叠加 visibility: hidden,结果动画直接消失——因为 visibility 生效是即时的,opacity 还没开始变,元素就不可见了。
visibility: hidden 不可过渡,它和 opacity 不是协同关系,而是互斥开关。真要用 visibility,只能放在 transition 结束后作为 cleanup 步骤。
- 淡出阶段:只靠
opacity+transition控制视觉渐隐 - 淡出完成:在
transitionend回调里设visibility: hidden或直接remove() - 绝对不要写
opacity-0 visibility-hidden同时生效 —— 这会让浏览器放弃 opacity 动画
骨架屏淡出时,真实内容要同步入场,避免布局抖动
常见翻车:骨架层刚 opacity: 0,真实图片就立刻加载并撑开容器,页面猛地一跳。这不是 CSS 问题,而是 DOM 层级和样式没对齐。
关键不是“怎么让骨架走”,而是“怎么让内容稳着进”。真实内容必须和骨架层尺寸完全一致,且初始不可见。
- 真实
<img>要套在和骨架同尺寸的容器里,设position: absolute盖住骨架 - 初始状态:
opacity: 0+visibility: hidden,等onload后只加一个is-loaded类 -
.is-loaded里只写opacity: 1+visibility: visible,靠同一组transition: opacity 0.3s ease衔接 - 骨架层如果是
::before,记得在.is-loaded::before里加display: none