WebberUI

Horizontal Scroll Section

以縱向滾動驅動橫向位移的釘住區段,內建彈簧手感、進度條與邊緣淡出。

載入預覽⋯

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

16
90
26
<HorizontalScrollSection />

安裝

npx shadcn@latest add https://webberui.com/r/horizontal-scroll-section.json

或在 components.json 設定 registries 後,改用 @webberui/horizontal-scroll-section 安裝。

安裝依賴後,從 registry JSON(/r/horizontal-scroll-section.jsonfiles[0].content)複製 horizontal-scroll-section.tsx 原始碼到你的 components/ui/ 目錄:

npm install motion clsx tailwind-merge

使用

外層區段會依內容寬度自動撐出一段縱向捲動高度;使用者往下捲動時,內部軌道被釘在畫面中央並向左位移。每個直接子元素是一張橫向面板。

import { HorizontalScrollSection } from "@/components/ui/horizontal-scroll-section";

<HorizontalScrollSection gap={24} showProgress>
  {items.map((item) => (
    <div key={item.id} className="h-80 w-96 rounded-xl border p-6">
      {item.content}
    </div>
  ))}
</HorizontalScrollSection>;

若區段位於巢狀的 overflow-y-auto 容器內,把該容器的 ref 傳給 container,元件會以它為釘住與捲動的參考:

const scrollerRef = React.useRef<HTMLDivElement>(null);

<div ref={scrollerRef} className="h-[80vh] overflow-y-auto">
  <HorizontalScrollSection container={scrollerRef}>
    {/* 面板 */}
  </HorizontalScrollSection>
</div>;

Props

Prop型別預設值說明
childrenReact.ReactNode依序水平排列的面板,每個直接子元素為一張
containerReact.RefObject<HTMLElement | null>巢狀捲動容器的 ref;預設以視窗為參考
gapnumber16面板之間的水平間距(px)
smoothbooleantrue以彈簧平滑位移,帶慣性阻尼;關閉則與捲動 1:1
stiffnessnumber90彈簧勁度(smooth 為 true 時生效)
dampingnumber26彈簧阻尼(smooth 為 true 時生效)
showProgressbooleanfalse在釘住區底部顯示水平進度條
fadeEdgesbooleanfalse左右邊緣以遮罩淡出,暗示尚有內容
ariaLabelstring"橫向捲動區段"套用在捲動區段上的無障礙標籤
classNamestring外層區段(決定總捲動高度)
viewportClassNamestring釘住的可視視窗容器
trackClassNamestring水平軌道

細節

  • 自動量測:以 ResizeObserver 量測軌道 scrollWidth 與可視視窗寬度,推導出「軌道寬 − 視窗寬」的縱向捲動距離,並據此撐出外層區段高度。內容、視窗或容器尺寸改變時會自動重新計算。
  • 釘住位移:內部視窗以 sticky top-0 釘住,useScroll 讀取區段進度後透過 useTransform 映射為水平位移 xsmooth 開啟時再經 useSpring 阻尼,得到柔和的慣性收尾。
  • 首幀正確:量測在 layout effect 中同步執行,第一幀即帶正確高度,避免版面跳動。所有計時器、ResizeObserver 與事件監聽於卸載時完整清理。
  • 調校stiffness / damping 控制手感,gap 控制面板間距;面板的寬高由你在 children 上自訂(範例使用 w-56 h-40)。

可及性

  • 使用者系統開啟「減少動態效果」時,改以原生 overflow-x-auto 水平捲動呈現,內容完整可及,且不佔用長段縱向捲動。
  • 捲動區段帶 role="region" 與可自訂的 aria-label
  • 鍵盤 Tab 聚焦到目前不在視窗內的面板時,會換算成對應的縱向捲動位置,把該面板平滑帶進可視範圍,避免焦點消失在畫面外。

On this page