Vertical Writing Spread
以 CSS writing-mode 建構的中日文直排編輯版面,直欄自右向左流動、橫排引文與圖片穿插其間,進場逐字自上而下顯影,並支援水平捲動推進欄序。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
32
0.05
0.7
<VerticalWritingSpread />
安裝
npx shadcn@latest add https://webberui.com/r/vertical-writing-spread.json或在 components.json 設定 registries 後,改用 @webberui/vertical-writing-spread 安裝。
安裝依賴後,從 registry JSON(/r/vertical-writing-spread.json 的 files[0].content)複製 vertical-writing-spread.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge使用
以 VerticalWritingSpread 作為容器,內部依閱讀順序放入直排的 VerticalColumn 與橫排的 HorizontalInsert。版面自右向左流動,第一欄位於最右端;容器需要一個固定高度(直欄以此填滿):
import {
VerticalWritingSpread,
VerticalColumn,
HorizontalInsert,
} from "@/components/ui/vertical-writing-spread";
<VerticalWritingSpread className="h-[320px]" showProgress fadeEdges>
<VerticalColumn variant="heading">直排的秩序</VerticalColumn>
<VerticalColumn>正文以直欄流動,自右向左閱讀……</VerticalColumn>
<HorizontalInsert>
<blockquote>「留白不是空白,而是呼吸。」</blockquote>
</HorizontalInsert>
<VerticalColumn>橫排引文與圖片穿插其間,成為視線的停頓……</VerticalColumn>
<VerticalColumn variant="heading">版面即敘事</VerticalColumn>
</VerticalWritingSpread>直欄在進入可視範圍時逐字自上而下顯影;預設開啟 wheelToHorizontal,垂直滾輪會轉為水平推進欄序,捲到兩端邊界時自動放行頁面捲動。
Props
VerticalWritingSpread
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | React.ReactNode | — | 依閱讀順序放入 VerticalColumn 與 HorizontalInsert,自右向左排列 |
gap | number | 32 | 欄與欄之間的水平間距(px) |
columnHeight | number | string | "100%" | 直欄高度;預設填滿容器,容器需自帶固定高度 |
wheelToHorizontal | boolean | true | 將垂直滾輪轉為水平推進欄序,邊界處放行頁面捲動 |
showProgress | boolean | false | 在底部顯示水平閱讀進度條 |
fadeEdges | boolean | false | 左右邊緣以遮罩淡出,暗示尚有內容可捲 |
stagger | number | 0.05 | 直欄大標逐字進場的每字間隔(秒) |
duration | number | 0.7 | 單欄/單字進場時長(秒) |
once | boolean | true | 只在第一次進入可視範圍時播放進場動畫 |
ariaLabel | string | "直排跨頁版面" | 套用在可捲動區段的無障礙標籤 |
className | string | — | 附加到外層可捲動容器(在此設定高度)的 class |
trackClassName | string | — | 附加到內層水平軌道的 class(如左右內距) |
VerticalColumn
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
variant | "heading" | "body" | "body" | heading 為直排大標(純字串時逐字進場),body 為直排正文 |
children | React.ReactNode | — | 欄內容;大標傳入字串可逐字顯影 |
writingMode | "vertical-rl" | "vertical-lr" | "vertical-rl" | 直排文字方向 |
className | string | — | 附加到欄容器的 class |
HorizontalInsert
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | React.ReactNode | — | 穿插於直排欄之間的橫排區塊:引文、圖片或圖說 |
align | "start" | "center" | "end" | "center" | 在直排流中的垂直對齊位置 |
className | string | — | 附加到區塊容器的 class |
細節
- 直排以 CSS
writing-mode: vertical-rl建構,正文沿垂直方向落下、自動換行成多個直行;HorizontalInsert以horizontal-tb打斷直排流,承載橫排引文與圖片 - 版面自右向左:軌道採
flex-row-reverse,第一欄位於最右端,掛載時自動捲至最右,符合中日文閱讀方向 - 進場偵測以 IntersectionObserver(root 為捲動容器)驅動;大標逐字自上而下 stagger 顯影,正文欄以
clip-path由上而下揭示 wheelToHorizontal將垂直滾輪映射為水平推進,向下捲動使欄序前進(向左);到達兩端邊界時放行頁面捲動,不會鎖住滾動
可及性
- 捲動區段為可聚焦的
role="region",帶aria-label;ArrowDown/Space前進、ArrowUp後退,並依 reduced motion 切換平滑或即時捲動 - 逐字大標保留
sr-only的完整文字,拆分後的字素對輔助科技隱藏(aria-hidden),朗讀時是完整詞句 - 使用者系統開啟「減少動態效果」時,直排版面與水平捲動保留,僅停用進場的顯影與 stagger 動畫(內容即刻完整呈現)