Custom Scrollbar
可客製的動畫自訂捲軸,spring 追隨捲動、滑塊可拖曳、點軌道跳轉。
以 motion/react spring 驅動的自訂捲軸:隱藏原生捲軸,改用可拖曳、可點軌道跳轉、支援漸層與 autoHide 的滑塊,並在捲動時帶一點慣性回饋。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add custom-scrollbarCustom Scrollbar 是用 React、Tailwind CSS 與 Motion 做的自訂捲軸(custom scrollbar)元件:包住一個固定高度的捲動區,隱藏瀏覽器原生捲軸,捲動本身仍由原生行為處理,只把滑塊換成可自訂顏色與寬度的版本。
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
<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 | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | React.ReactNode | — | 要包裹並可捲動的內容 |
maxHeight | number | string | 300 | 內容區最大高度,超出即可捲動 |
width | number | 8 | 捲軸寬度(px) |
thumbColor | string | 靛紫漸層 | 滑塊顏色,可傳 CSS 漸層字串 |
thumbHoverColor | string | — | 滑鼠移入捲軸時的滑塊顏色 |
trackColor | string | rgba(120,120,140,0.14) | 軌道底色 |
showTrack | boolean | true | 是否顯示軌道底色 |
autoHide | boolean | false | 靜止時淡出,捲動、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)。