覆蓋層與回饋

Custom Scrollbar

可客製的動畫自訂捲軸,spring 追隨捲動、滑塊可拖曳、點軌道跳轉。

以 motion/react spring 驅動的自訂捲軸:隱藏原生捲軸,改用可拖曳、可點軌道跳轉、支援漸層與 autoHide 的滑塊,並在捲動時帶一點慣性回饋。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add custom-scrollbar

還沒有專案,或安裝遇到問題?看快速開始 →

Custom Scrollbar 是用 React、Tailwind CSS 與 Motion 做的自訂捲軸(custom scrollbar)元件:包住一個固定高度的捲動區,隱藏瀏覽器原生捲軸,捲動本身仍由原生行為處理,只把滑塊換成可自訂顏色與寬度的版本。

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

300
8
編輯中的呼叫預設屬性
<CustomScrollbar/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

適用情境

  • 卡片或側欄裡的長清單,例如通知列表、聊天訊息、檔案清單,希望捲軸顏色跟品牌色一致。
  • 深色介面或設計感較重的面板,原生捲軸在不同作業系統外觀不一致時。
  • Dashboard 小工具裡的捲動區,用 autoHide 讓捲軸平時不佔視覺。
  • 不適合:整頁捲動。元件需要以 maxHeight 限定一個區塊的高度,只處理垂直方向。

安裝

npx webberui@latest add https://webberui.com/r/custom-scrollbar.json

或在 components.json 設定 registries 後,改用 @webberui/custom-scrollbar 安裝。

使用

import { CustomScrollbar } from "@/components/ui/custom-scrollbar";

<CustomScrollbar maxHeight={280} width={9} autoHide>
  <div className="p-5">{/* 你的長內容 */}</div>
</CustomScrollbar>

maxHeight 決定內容區高度,超出即可捲動。滑塊高度會依內容比例自動計算。傳入 CSS 漸層字串到 thumbColor 即可做出彩色捲軸。

範例

通知列表、靜止時隱藏捲軸

autoHide 讓捲軸在靜止時淡出,捲動、滑鼠移入或拖曳時再出現。

import { CustomScrollbar } from "@/components/ui/custom-scrollbar";

const notifications = [
  { id: 1, title: "部署完成", time: "2 分鐘前" },
  { id: 2, title: "新成員加入工作區", time: "1 小時前" },
  { id: 3, title: "帳單已寄出", time: "昨天" },
  // ...
];

export function NotificationList() {
  return (
    <CustomScrollbar maxHeight={320} autoHide className="border">
      <ul className="divide-y">
        {notifications.map((n) => (
          <li key={n.id} className="flex justify-between px-4 py-3 text-sm">
            <span>{n.title}</span>
            <span className="text-muted-foreground">{n.time}</span>
          </li>
        ))}
      </ul>
    </CustomScrollbar>
  );
}

單色滑塊與 hover 顏色

thumbColor 接受任何 CSS 背景值,傳單色字串就不會是漸層;thumbHoverColor 設定滑鼠移入時的顏色,showTrack={false} 拿掉軌道底色。

<CustomScrollbar
  maxHeight={240}
  width={6}
  thumbColor="#a1a1aa"
  thumbHoverColor="#52525b"
  showTrack={false}
>
  <nav className="space-y-1 p-3">{/* 側欄連結 */}</nav>
</CustomScrollbar>

用字串指定高度

maxHeight 也接受字串,例如 rem 或 calc()。請避免 vh、dvh 等視口單位。

<CustomScrollbar maxHeight="24rem">
  <div className="p-5">{/* 長內容 */}</div>
</CustomScrollbar>

Props

Prop型別預設值說明
childrenReact.ReactNode—要包裹並可捲動的內容
maxHeightnumber | string300內容區最大高度,超出即可捲動
widthnumber8捲軸寬度(px)
thumbColorstring靛紫漸層滑塊顏色,可傳 CSS 漸層字串
thumbHoverColorstring—滑鼠移入捲軸時的滑塊顏色
trackColorstringrgba(120,120,140,0.14)軌道底色
showTrackbooleantrue是否顯示軌道底色
autoHidebooleanfalse靜止時淡出,捲動、hover 或拖曳時淡入

可及性

  • 使用者系統開啟「減少動態效果」時,滑塊即時追隨捲動、不套用 spring 慣性
  • 原生捲動行為完整保留(滾輪、觸控、鍵盤);自訂滑塊層帶 aria-hidden,僅作視覺回饋
  • 嚴禁使用 100vh 等視口高度單位;請以 maxHeight 給定明確界線

常見問題

可以在 Next.js App Router 使用嗎?

可以。原始碼已有 "use client",在 Server Component 頁面直接 import 即可;尺寸量測都在 effect 裡進行,伺服器端輸出不需要 window。

鍵盤和觸控捲動還能用嗎?

可以。實際捲動的仍是原生 overflow-y: auto 的容器,滾輪、觸控與鍵盤捲動都保留,自訂滑塊只是疊在上面的視覺層,並以 aria-hidden 對輔助科技隱藏。

內容高度改變時,滑塊會更新嗎?

會。元件用 ResizeObserver 同時監看容器與內容,尺寸變動就重新計算滑塊高度與位置。內容沒有超出 maxHeight 時不顯示捲軸。

支援水平捲軸嗎?

不支援。捲動區設定為 overflow-x-hidden,元件只處理垂直方向。

怎麼改顏色和寬度?

用 thumbColor、thumbHoverColor、trackColor 設定顏色(都接受 CSS 字串,包含漸層),width 設定捲軸寬度(px,預設 8)。