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。