UI 动效 007:Skeleton Shimmer,为什么灰色占位条会扫一下
2026/7/1 · 8:11

UI 动效 007:Skeleton Shimmer,为什么灰色占位条会扫一下

这期拆解 Skeleton Shimmer / 骨架屏扫光:它适合页面结构已确定但数据还没返回的场景,关键是先画出接近真实内容的占位骨架,再用渐变扫光和内容淡入降低等待感。文中用自制 GIF 与 CSS 示例说明怎么让灰色占位条动起来。

一张卡片还没加载出来,页面先出现几条灰色圆角块;过一会儿,一束浅色高光从左到右扫过去,真实内容再淡进来。这个动效通常叫 Skeleton Shimmer / 骨架屏扫光。它不是真的让接口更快,而是先告诉用户「这里会有什么」,避免页面空白得像坏了一样。
Material Design 3 把 Skeleton loaders 归在转场模式里:它们用临时 loading state 过渡到完整 UI,并用内容即将出现的位置降低感知等待和版式跳动。1 NN/g 对 skeleton screen 的定义也很接近:加载时显示一个类似线框图的页面结构,让用户先建立对最终页面的预期。2
骨架屏扫光动效示意
骨架屏扫光动效示意
自制 GIF 示意骨架屏从灰色占位、扫光提示到真实内容淡入,非真实产品截图。

它适合什么时候用

Skeleton Shimmer 最适合「页面结构确定,但数据还没回来」的场景:信息流卡片、商品列表、用户资料页、仪表盘模块都可以用。MUI 的 Skeleton 组件文档也把它定义为「数据加载前显示内容预览」,并提供 text、circular、rectangular 等形状,动画可以是默认 pulsate,也可以改成 wave 或关闭。3
别把它当万能 loading。NN/g 的建议很直接:skeleton 更适合全页或大块内容加载;单个卡片、视频模块可以用 spinner;超过 10 秒的等待更应该给 progress bar,因为用户需要知道还要等多久;如果页面 1 秒内就出来,闪一下 skeleton 反而会烦。2
我一般用这三条判断要不要上:
  • 内容版式稳定:标题、图片、摘要、按钮这些位置基本固定,骨架才有意义。
  • 等待不是瞬间结束:太短会闪屏,太长会让用户觉得被糊弄。
  • 真实内容能渐进替换:拿到哪块数据就替换哪块,不要等全部接口完成后才一起出现。

为什么扫一下会让等待更「有方向」

骨架屏有两个层次。第一层是灰色块,它让用户看到最终页面的大致结构;第二层是 shimmer,也就是那束移动高光。高光的作用不是装饰,而是告诉用户「系统还在工作」。Material Design 3 也提到,skeleton loaders 会用细微的 pulsing animation 表示不确定进度,内容加载完后再快速淡入。1
这和 spinner 的心理感受不一样。Spinner 只说「请等一下」,但没有告诉你等完会看到什么;骨架屏先把版式摆出来,用户的眼睛会自然预读那些灰色区域:这里是头像,这里是标题,这里可能是图片。等真实内容出现时,变化就不是突然砸下来,而是「影子变成实体」。
扫光要轻。太亮、太快、循环太密,会抢走用户对内容本身的注意力。NN/g 也提醒,animated skeleton 可能造成分心、烦躁,甚至带来可访问性问题。2 所以它更像呼吸灯,不该像舞台追光。

实现原理:固定骨架 + 移动渐变

Web 端最常见的做法是把每个占位块画成圆角矩形,再给它叠一层线性渐变。CSS 的 linear-gradient() 可以生成沿直线变化的颜色带,MDN 对 CSS gradients 的说明里也提到,渐变可以直接作为背景使用。4
高光怎么动?把背景做得比元素本身更宽,然后用 background-position 改变背景图的位置。MDN 对 background-position 的定义是:它设置每个背景图的初始位置。5 再用 @keyframes 定义从起点到终点的中间步骤,浏览器就会把这束高光平滑扫过去;@keyframes 本来就是用来控制 CSS 动画序列中间步骤的规则。6
.skeleton {
  border-radius: 12px;
  background: linear-gradient(
    100deg,
    #e6ebf4 0%,
    #e6ebf4 38%,
    #ffffff 50%,
    #e6ebf4 62%,
    #e6ebf4 100%
  );
  background-size: 220% 100%;
  animation: shimmer 1.2s linear infinite;
}

@keyframes shimmer {
  from { background-position: 120% 0; }
  to   { background-position: -120% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
}
这段代码里最重要的不是颜色,而是三件事:
  1. 骨架尺寸要接近真实内容。标题不要画成长段,头像不要画成方块。占位越像最终内容,替换时越稳。
  2. 高光只改变背景,不改变布局。不要用真正的元素横向移动,否则会多出重排和遮挡问题。
  3. 真实内容淡入,骨架淡出。直接把骨架删掉会出现跳变;短暂交叉淡入能让视觉更顺。

做坏时,问题通常不在动画,而在版式

Skeleton Shimmer 很容易被做成「一屏灰条」。灰条数量太多,用户会看不出层级;灰条和最终内容差得太远,内容出现时还是会跳;页面已经很快,却硬要先闪一层 skeleton,体验会更碎。
一个好用的骨架屏应该像低保真预览:图片区域就是图片比例,标题区域只给一两行,次要信息更淡一点,按钮和头像保留形状。移动的高光只负责说明「还在加载」,真正降低焦虑的是稳定的结构。
如果只能记一条:先画对影子,再让影子轻轻动一下。Skeleton Shimmer 的动效不是主角,主角是用户在等待时仍然知道自己将要看到什么。

相似内容

围绕这条内容继续补充观点或上下文。

  • 登录后可发表评论。