SwRail
SwRail 是橫向自由捲動的內容橫排元件,適合「一行 N 個卡片、視口放不下靠捲動」的場景(影/漫/小說封面推薦、文字連結橫排等)。
它基於原生 scroll + CSS scroll-snap:行動端 / 平板的手指滑動與慣性由瀏覽器原生提供(無需任何額外設定);桌面端自帶一對預設左右箭頭(hover 容器時浮現、到頭/尾自動禁用),無需額外設定。SSR 下作為原生可捲容器漸進增強(無 JS 也能捲)。
不做輪播:SwRail 沒有
loop/autoplay—— 自動輪播 banner 請用SwCarousel;SwRail 只負責「自由橫排捲動」。
基礎用法
預設 slot 放卡片即可——桌面端會自動渲染一對左右箭頭(僅 hover 裝置顯示、行動端隱藏、到頭/尾自動禁用),無需寫任何控制項程式碼。卡片間距用 CSS 變數 --sw-rail-gap 控制。
橫排捲動 + 預設箭頭
<SwRail aria-label="推薦影片" style="--sw-rail-gap: 0.75rem">
<Card v-for="m in list" :key="m.id" :item="m" />
</SwRail>
不想要預設箭頭時傳 :arrows="false" 關掉:
<SwRail aria-label="推薦影片" :arrows="false">
<Card v-for="m in list" :key="m.id" :item="m" />
</SwRail>
控制的三層(按需選)
SwRail 提供三種方式翻頁,按需求複雜度遞進選用:
- 預設箭頭(最省事):什麼都不傳,自帶一對左右箭頭。僅桌面(
@media hover)顯示、行動端隱藏(手指滑即可)、到頭/尾自動禁用。四態樣式(靜止半透明 / hover 容器出底色 / hover 按鈕全白 / disabled 同靜止態對稱)全部由 CSS 變數驅動(見下方「CSS 變數」)。 #controls插槽(自訂控制項):需要完全自訂箭頭/控制項外觀時用#controls作用域插槽,拿到scrollPrev/scrollNext/canPrev/canNext自行渲染。傳了#controls即覆蓋預設箭頭(不再渲染內建箭頭)。defineExpose(任意位置放按鈕):想把翻頁按鈕放到 rail 以外的頁面任意位置(如區塊標題旁),用樣板 ref 拿scrollPrev/scrollNext/canPrev/canNext自己綁(見「命令式控制」)。
#controls 插槽(自訂控制項)
#controls 插槽自訂控制項
<SwRail aria-label="推薦影片" style="--sw-rail-gap: 0.75rem">
<Card v-for="m in list" :key="m.id" :item="m" />
<template #controls="{ scrollPrev, scrollNext, canPrev, canNext }">
<button :disabled="!canPrev" @click="scrollPrev()">‹</button>
<button :disabled="!canNext" @click="scrollNext()">›</button>
</template>
</SwRail>
吸附與捲動距離
snap控制 CSSscroll-snap-type強度:'proximity'(預設,輕吸附)/'mandatory'(強制每項吸附)/'none'(自由捲不吸附)。scrollBy控制箭頭每次捲動距離:'page'(預設,約一屏寬的 90%)或具體像素數。行動端手指滑動的「慣性翻幾個」由原生捲動決定,不受此 prop 影響。
snap 三種吸附強度對比
<!-- 強吸附 + 箭頭每次捲 600px -->
<SwRail snap="mandatory" :scroll-by="600">
<Card v-for="..." />
</SwRail>
命令式控制
透過樣板 ref 呼叫暴露方法:
<script setup>
const railRef = ref()
</script>
<template>
<SwRail ref="railRef"><Card v-for="..." /></SwRail>
<button @click="railRef.scrollNext()">下一組</button>
</template>
鍵盤與無障礙
- 容器可聚焦:方向鍵
←/→翻一段,Home/End捲到首 / 尾。 - 傳
ariaLabel時輸出role="region"+aria-label(不傳則不輸出,避免無名 region)。 - 命中系統「減少動態」(
prefers-reduced-motion)時捲動自動改為瞬時無動畫。
Props
| 名稱 | 型別 | 必填 | 預設值 | 說明 |
|---|---|---|---|---|
snap | 'none' | 'proximity' | 'mandatory' | 'proximity' | 對應 CSS scroll-snap-type 強度 | |
scrollBy | 'page' | number | 'page' | 箭頭每次捲動距離('page'≈容器寬 0.9 / number=像素) | |
arrows | boolean | true | 是否渲染預設左右箭頭。傳了 #controls 插槽則以插槽為準(不渲預設箭頭);false 整體關掉預設箭頭 | |
ariaLabel | string | undefined | 傳了才輸出 role="region" + aria-label |
卡片間距用 CSS 變數
--sw-rail-gap(預設0.75rem,基線不黏連;可顯式覆蓋任意值含0)控制,不走 prop。
Events
SwRail 目前不派發事件。
Slots
| 插槽名 | 作用域參數 | 說明 |
|---|---|---|
default | — | 卡片內容(v-for 提供);子項自動 flex: 0 0 auto 不收縮 |
controls | { scrollPrev, scrollNext, canPrev, canNext } | 自訂控制項(覆蓋預設箭頭),由呼叫方渲染業務樣式 |
暴露方法(defineExpose)
| 成員 | 簽章 | 說明 |
|---|---|---|
scrollPrev | (opts?: { immediate?: boolean }) => void | 向左捲一段(immediate 無動畫) |
scrollNext | (opts?: { immediate?: boolean }) => void | 向右捲一段 |
refresh | () => void | 內容 / 尺寸變化後手動重算 canPrev / canNext |
canPrev | Readonly<Ref<boolean>> | 是否還能向左捲(到最左為 false) |
canNext | Readonly<Ref<boolean>> | 是否還能向右捲(到最右為 false) |
scrollToStart | () => void | 平滑滾回起點——列表刷新 / 換資料後復位到頭的官方入口 |
scrollTo | (left: number) => void | 平滑滾到指定橫向位置 |
CSS 變數
預設箭頭的樣式全部透過 CSS 變數客製,寫在 SwRail 元素或其祖先上即可覆蓋。卡片間距同樣走變數。
CSS 變數客製箭頭(更大 / 常顯 / 深色底)
非同步載入後 refresh()(SR-002)
| 變數 | 預設值 | 說明 |
|---|---|---|
--sw-rail-gap | 0.75rem | 卡片間距(基線不黏連,可覆蓋含 0) |
--sw-rail-arrow-color | rgb(255 255 255) | 箭頭圖示色(預設白) |
--sw-rail-arrow-bg | rgb(0 0 0 / 40%) | hover 容器時箭頭底色(預設半透明黑,非主色) |
--sw-rail-arrow-size | 2.25rem | 箭頭按鈕尺寸 |
--sw-rail-arrow-offset | 0.5rem | 箭頭距左右邊的橫向距離 |
--sw-rail-arrow-top | 50% | 箭頭垂直錨點(translateY(-50%) 對齊該線中心)。卡片是「封面 + 下方標題/標籤」結構時設 calc((100% - <文字區高>) / 2) 讓箭頭對齊封面圖垂直中心 |
--sw-rail-arrow-radius | 999px | 箭頭圓角(預設圓形) |
--sw-rail-arrow-opacity | 0.55 | 靜止態透明度(半透明箭頭無底;disabled 態同此值,保持左右對稱) |
--sw-rail-arrow-hover-opacity | 1 | hover 按鈕本身時的透明度(全白) |
<!-- 把箭頭底色換成深色、加大尺寸 -->
<SwRail
aria-label="推薦影片"
style="
--sw-rail-gap: 1rem;
--sw-rail-arrow-bg: rgb(0 0 0 / 60%);
--sw-rail-arrow-size: 3rem;
"
>
<Card v-for="m in list" :key="m.id" :item="m" />
</SwRail>
預設箭頭僅在 hover 裝置(桌面)顯示,行動端整體隱藏(手指滑動即可)。四態:①靜止(半透明、無底色)②hover 容器(出現
--sw-rail-arrow-bg底色)③hover 按鈕本身(箭頭全白不透明)④disabled(到頭/尾,外觀同①、不可點)。
注意事項
- 子項不收縮:SwRail 內部對直接子元素設了
flex: 0 0 auto,請給卡片明確寬度(否則無內容撐開則不溢出、無法捲動)。 - 自動輪播請用
SwCarousel:SwRail 刻意不含loop/autoplay。 - 三端:行動 / 平板觸控捲動是瀏覽器原生行為,無需額外設定;桌面端自帶預設箭頭(hover 顯示),需要自訂控制項或把按鈕放別處時再用
#controls插槽 /defineExpose。