Frontend Lab
← 回到所有模式
PD06📊 Data Display · 資料展示載入

Skeleton

骨架載入

難度 ★★★★標籤 skeleton · pulse · 載入3 min read

模式簡述

Skeleton:載入時的灰色佔位形狀。比 spinner 更精準傳達「會有什麼」的預期。

文字|標題 + 3 行內文

Claude Code Prompt

💬 Claude Code Prompt
參考:PD06 skeleton
組件:Skeleton.tsx

Skeleton:載入時的灰色佔位形狀。比 spinner 更精準傳達「會有什麼」的預期。

限制:
- 形狀和實際內容不像
- pulse 動畫太快
- 永遠不消失

完整程式碼

Skeleton.tsx
"use client";

type State = "text" | "card" | "list";

export function Skeleton({ state = "card" }: { state?: State }) {
if (state === "text") {
  return (
    <div className="w-full max-w-md space-y-3">
      <div className="h-6 w-2/3 animate-pulse rounded bg-muted" />
      <div className="space-y-2">
        <div className="h-3 w-full animate-pulse rounded bg-muted" />
        <div className="h-3 w-full animate-pulse rounded bg-muted" />
        <div className="h-3 w-3/4 animate-pulse rounded bg-muted" />
      </div>
    </div>
  );
}
if (state === "list") {
  return (
    <ul className="w-full max-w-md space-y-3">
      {[0, 1, 2, 3, 4].map((i) => (
        <li key={i} className="flex items-center gap-3">
          <div className="h-9 w-9 shrink-0 animate-pulse rounded-full bg-muted" />
          <div className="flex-1 space-y-1.5">
            <div className="h-3 w-1/2 animate-pulse rounded bg-muted" />
            <div className="h-2.5 w-3/4 animate-pulse rounded bg-muted" />
          </div>
        </li>
      ))}
    </ul>
  );
}
return (
  <div className="w-full max-w-sm overflow-hidden rounded-lg border border-border bg-background/30">
    <div className="aspect-[16/9] w-full animate-pulse bg-muted" />
    <div className="space-y-2 p-3">
      <div className="h-4 w-2/3 animate-pulse rounded bg-muted" />
      <div className="h-3 w-full animate-pulse rounded bg-muted" />
      <div className="h-3 w-1/2 animate-pulse rounded bg-muted" />
    </div>
  </div>
);
}

何時用

  • ✅ 首屏資料載入
  • ✅ API 還在 fetch 時的過渡
  • ✅ 圖片載入前的位置佔位

何時別用

  • ❌ 極短的等待(< 200ms 不需要,spinner 也行)
  • ❌ 資料量不可預期時(用 spinner)
  • ❌ 錯誤時(不要假裝在 loading)

我踩過的坑

  1. 形狀和實際內容不像:使用者預期看到頭像,loading 出來是長條。要對應實際 layout。

  2. pulse 動畫太快:每秒 1 次 OK,每秒 3 次反而焦慮。

  3. 永遠不消失:API fail 後還是在 pulse,使用者以為當機。記得 fail 後切到 error state。

相關模式

  • PD05
  • PD07

搜尋

按 ⌘K 隨時開啟