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 提供三種方式翻頁,按需求複雜度遞進選用:

  1. 預設箭頭(最省事):什麼都不傳,自帶一對左右箭頭。僅桌面(@media hover)顯示、行動端隱藏(手指滑即可)、到頭/尾自動禁用。四態樣式(靜止半透明 / hover 容器出底色 / hover 按鈕全白 / disabled 同靜止態對稱)全部由 CSS 變數驅動(見下方「CSS 變數」)。
  2. #controls 插槽(自訂控制項):需要完全自訂箭頭/控制項外觀時用 #controls 作用域插槽,拿到 scrollPrev / scrollNext / canPrev / canNext 自行渲染。傳了 #controls 即覆蓋預設箭頭(不再渲染內建箭頭)。
  3. 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 控制 CSS scroll-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=像素)
arrowsbooleantrue是否渲染預設左右箭頭。傳了 #controls 插槽則以插槽為準(不渲預設箭頭);false 整體關掉預設箭頭
ariaLabelstringundefined傳了才輸出 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
canPrevReadonly<Ref<boolean>>是否還能向左捲(到最左為 false)
canNextReadonly<Ref<boolean>>是否還能向右捲(到最右為 false)
scrollToStart() => void平滑滾回起點——列表刷新 / 換資料後復位到頭的官方入口
scrollTo(left: number) => void平滑滾到指定橫向位置

CSS 變數

預設箭頭的樣式全部透過 CSS 變數客製,寫在 SwRail 元素或其祖先上即可覆蓋。卡片間距同樣走變數。

CSS 變數客製箭頭(更大 / 常顯 / 深色底)

加载中...

非同步載入後 refresh()(SR-002)

加载中...
變數預設值說明
--sw-rail-gap0.75rem卡片間距(基線不黏連,可覆蓋含 0)
--sw-rail-arrow-colorrgb(255 255 255)箭頭圖示色(預設白)
--sw-rail-arrow-bgrgb(0 0 0 / 40%)hover 容器時箭頭底色(預設半透明黑,非主色)
--sw-rail-arrow-size2.25rem箭頭按鈕尺寸
--sw-rail-arrow-offset0.5rem箭頭距左右邊的橫向距離
--sw-rail-arrow-top50%箭頭垂直錨點(translateY(-50%) 對齊該線中心)。卡片是「封面 + 下方標題/標籤」結構時設 calc((100% - <文字區高>) / 2) 讓箭頭對齊封面圖垂直中心
--sw-rail-arrow-radius999px箭頭圓角(預設圓形)
--sw-rail-arrow-opacity0.55靜止態透明度(半透明箭頭無底;disabled 態同此值,保持左右對稱)
--sw-rail-arrow-hover-opacity1hover 按鈕本身時的透明度(全白)
<!-- 把箭頭底色換成深色、加大尺寸 -->
<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。