版面構圖
捲動漸隱清單
上下邊緣漸隱高度隨剩餘可捲距離即時變化的 React 捲動清單元件:到頂不顯示上方漸層、到底不顯示下方漸層,可選自動捲動並在滑鼠移入、聚焦或觸控時暫停。
長清單放進固定高度的區塊時,上下邊緣的漸層能提示「還有內容」——但到頂了還留著上方漸層,就會把第一筆蓋得半透明。這個元件的漸層高度直接等於剩餘可捲距離(上限 maxFadeHeight):越接近頂端,上方漸層越薄,到頂完全消失;底部同理。可用 items + renderItem 輸出語意化的 <ul>,也可直接放 children;需要跑馬燈式的公告欄時,開 autoScroll 即可。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add scroll-fade-listPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
76
320
24
編輯中的呼叫預設屬性
<ScrollFadeList/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/scroll-fade-list.json或在 components.json 設定 registries 後,改用 @webberui/scroll-fade-list 安裝。
使用
import { ScrollFadeList } from "@/components/ui/scroll-fade-list";
const areas = [
{ name: "臺北市中正區", zip: "100" },
{ name: "臺中市西屯區", zip: "407" },
{ name: "高雄市苓雅區", zip: "802" },
];
<ScrollFadeList
items={areas}
getKey={(a) => a.zip}
height={280}
label="配送地區"
renderItem={(a) => (
<div className="flex justify-between px-3 py-2 text-sm">
<span>{a.name}</span>
<span className="font-mono tabular-nums">{a.zip}</span>
</div>
)}
/>放在非白色底上時,覆寫 --wb-sfl-bg 讓漸層的實色端與底色一致:
<ScrollFadeList
className="[--wb-sfl-bg:#fafafa] dark:[--wb-sfl-bg:#171717]"
autoScroll
>
{/* 任意內容 */}
</ScrollFadeList>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
items | T[] | — | 清單資料;與 renderItem、getKey 一組使用,提供時輸出 <ul>/<li> 結構,否則改渲染 children |
renderItem | (item: T, index: number) => ReactNode | — | 每筆資料的渲染函式;未提供時以 String(item) 顯示 |
getKey | (item: T, index: number) => Key | — | 每筆資料的 key;未提供時用索引 |
children | ReactNode | — | 未使用 items 時,直接放進捲動容器的內容 |
maxFadeHeight | number | 76 | 上下漸隱的最大高度(px);實際高度 = min(剩餘可捲距離, 此值) |
height | number | string | 320 | 捲動區高度;數字視為 px,也可傳任何 CSS 長度字串 |
autoScroll | boolean | false | 自動往下捲動,到底回到頂端重來;滑鼠移入、鍵盤聚焦、觸控時暫停,減少動態效果時忽略 |
gutter | number | 10 | 右側讓給捲軸的寬度(px),漸層不覆蓋這一段 |
label | string | "清單" | 捲動區的無障礙名稱(role="region" 的 aria-label) |
listClassName | string | — | 透傳到 <ul>(items 模式)或內容包裹層(children 模式) |
className | string | — | 透傳到最外層容器 |
CSS 變數
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
--wb-sfl-bg | color | #ffffff(dark:#0a0a0a) | 漸層的實色端,需與清單所在底色一致 |
--wb-sfl-auto-speed | number | 24 | 自動捲動速度(px/秒),元件每秒重讀一次 |
--top-fade-height | length | — | 由元件於捲動時寫入的上方漸層高度,勿手動設定 |
--bottom-fade-height | length | — | 由元件於捲動時寫入的下方漸層高度,勿手動設定 |
細節
- 捲動事件以
passive: true監聽並用requestAnimationFrame節流;每幀量測scrollTop(到頂距離)與scrollHeight − clientHeight − scrollTop(到底距離),各自夾在 0 到maxFadeHeight之間,以style.setProperty直接寫進 CSS 變數,不經 React state,捲動時清單不會重新渲染。 - 漸層高度刻意不加 transition:它就是剩餘距離本身,加動畫只會落後於手指。
ResizeObserver同時監看捲動容器與內容,資料增減、字型載入或換行改變內容高度時會重算。- 漸層是外層容器的
::before/::after,pointer-events: none不擋點擊;右側讓出gutter寬度,不蓋住捲軸。捲動容器設定scrollbar-gutter: stable與overscroll-behavior: contain。 - 自動捲動以浮點累加器記錄位置,每幀推進不到 1px 也能平順移動;使用者手動捲過後會從新位置接續。觸控結束後延遲約 1.5 秒才恢復,讓慣性捲動先跑完。
可及性
- 捲動容器為
role="region"並以label作為aria-label,tabIndex=0讓鍵盤使用者能聚焦後用方向鍵、Page Up/Page Down 捲動,聚焦時顯示 focus-visible 外框 items模式輸出帶role="list"的<ul>/<li>,螢幕閱讀器會朗讀項目數- 漸層是不含文字的偽元素,不會被輔助科技讀出,也不攔截指標事件
- 自動捲動在滑鼠移入、容器內任一元素取得焦點、觸控時暫停,不會在使用者閱讀或操作時把內容捲走
- 使用者系統開啟「減少動態效果」時,漸層照常(它不是動畫),只停用
autoScroll