跳到主要内容

Skeleton

  • 组件说明:内容加载时的占位块,带 115° 斜向循环扫光,避免布局跳动。
  • 组件组:Progress Indicators
  • 交互特征:115° 斜向扫光,2.4s 循环;遵循 prefers-reduced-motion
  • 实现约定ui 保留结构,design 层基于测量到的几何驱动扫光。测量就绪后才起扫,首帧保持纯灰。
  • Figma 规范Skeleton

基础用法

结果
Loading...
实时编辑器
render(<Skeleton className="h-4 w-[240px]" />)

卡片级扫光

传入 items 渲染多块:外层 div 作为整张「画布」,一道连续的光跨块扫过整张卡片,块与块之间的空隙保持纯灰。direction 控制画布主轴方向(默认 vertical);item 带 children 时变成嵌套子容器、按自身 direction 排布——例如「头像在左,右侧上下两行」。

结果
Loading...
实时编辑器
render(
  <Skeleton
    direction="horizontal"
    className="items-center gap-4"
    style={{ width: 320 }}
    items={[
      { className: 'size-12 rounded-full' },
      {
        direction: 'vertical',
        className: 'flex-1 gap-2',
        children: [{ className: 'h-4 w-full' }, { className: 'h-4 w-2/3' }],
      },
    ]}
  />,
)

文本行

结果
Loading...
实时编辑器
render(
  <Skeleton
    className="gap-3"
    style={{ width: 320 }}
    items={[{ className: 'h-4 w-full' }, { className: 'h-4 w-full' }, { className: 'h-4 w-2/3' }]}
  />,
)

卡片

结果
Loading...
实时编辑器
render(
  <Skeleton
    className="gap-3"
    style={{ width: 320 }}
    items={[{ className: 'h-[160px] w-full rounded-xl' }, { className: 'h-4 w-full' }, { className: 'h-4 w-2/3' }]}
  />,
)

Token

部位Token
圆角--radius-sm(0.25rem)
底色Grays/Gray-1#EBEBEB
扫光Grays/Gray-2#D6D6D6

暗色模式由 token 自动切换(变量本身分主题定义),组件内不写死色值。

Skeleton Props

继承原生 div 的所有属性(React.HTMLAttributes<HTMLDivElement>)。

属性类型默认值说明
itemsSkeletonItem[]多块配置。传入后外层 div 作为画布,内部各块共享一道连续扫光
direction'horizontal' | 'vertical''vertical'画布主轴方向(仅 items 模式)。自动加 flex + 方向类,gap / align 仍由 className 控制
classNamestring单块模式:控制宽高、形状;items 模式:补充画布布局(gap / align / grid 覆盖)

SkeletonItem{ className?: string; children?: SkeletonItem[]; direction?: 'horizontal' \| 'vertical'; key?: Key }。叶子节点(无 children)渲染一个骨架块;带 children 的节点改作子容器,按自身 direction(默认 vertical)递归排布。

使用约定

  • 单块 Skeleton 只负责渲染占位外壳,尺寸与形状完全由 className 驱动。
  • 多块组成一张卡片时传入 items,让扫光跨块连续、空隙保持纯灰。
  • 骨架形状应贴合真实内容布局,避免加载完成后出现布局跳动。
  • 不确定时长的旋转加载用 Spinner,可量化进度用 CircularProgress