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。