Scroll Text Highlight
文字隨滾動進度逐字(或逐詞)由淡灰轉為前景實色的閱讀高亮。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add scroll-text-highlightScroll Text Highlight 是用 React 與 Motion 的 useScroll 做的捲動文字高亮(scroll reveal text、捲動逐字點亮)元件:段落捲過畫面時,文字依序從淡灰轉為實色,可以逐字或逐詞進行,也支援巢狀捲動容器。
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
<ScrollTextHighlight/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
適用情境
- 品牌頁或「關於我們」的理念宣言段落,讓讀者跟著捲動節奏讀完
- 產品發表頁在兩段大圖之間的過場文字
- 長篇故事型頁面(scrollytelling)的重點引言
- 簡報式的單頁介紹,一個畫面只放一句話
安裝
npx webberui@latest add https://webberui.com/r/scroll-text-highlight.json或在 components.json 設定 registries 後,改用 @webberui/scroll-text-highlight 安裝。
使用
放在巢狀捲動容器內時,把容器的 ref 傳給 container:
import * as React from "react";
import { ScrollTextHighlight } from "@/components/ui/scroll-text-highlight";
export function Example() {
const scrollerRef = React.useRef<HTMLDivElement>(null);
return (
<div ref={scrollerRef} className="h-[300px] overflow-y-auto">
<div className="py-40">
<ScrollTextHighlight
container={scrollerRef}
text="隨著滾動逐字點亮的文字。"
className="text-xl font-semibold"
/>
</div>
</div>
);
}以整個視窗為捲動容器時,可省略 container:
<ScrollTextHighlight
by="word"
text="Scroll to reveal."
className="text-4xl font-bold"
/>範例
品牌理念區塊
每個 ScrollTextHighlight 各自追蹤自己的捲動進度,多段文字可以依序點亮。上下留白讓段落有足夠的捲動距離。
import { ScrollTextHighlight } from "@/components/ui/scroll-text-highlight";
const paragraphs = [
"我們相信好的工具應該安靜地待在背景。",
"所以每個元件都附上完整的程式碼,你可以讀、可以改,也可以整個拿走。",
];
export function Manifesto() {
return (
<section className="mx-auto max-w-3xl space-y-24 py-[40vh]">
{paragraphs.map((p) => (
<ScrollTextHighlight
key={p}
text={p}
className="text-3xl font-semibold leading-relaxed md:text-5xl"
/>
))}
</section>
);
}指定文字顏色
未亮起的部分是同一個顏色、透明度 0.2,所以只要用 className 設定字色,深淺模式各自調整即可。
<ScrollTextHighlight
text="三分鐘完成部署,不需要設定伺服器。"
className="text-4xl font-bold text-indigo-600 dark:text-indigo-300"
/>英文段落逐詞高亮
by="word" 以空白切分,適合英文等以空白分詞的語言,節奏比逐字慢一些。
<ScrollTextHighlight
by="word"
text="Ship faster with components you fully own."
className="text-5xl font-semibold tracking-tight"
/>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
text | string | — | 要隨滾動高亮的文字 |
by | "char" | "word" | "char" | 高亮的最小單位 |
container | RefObject<HTMLElement> | — | 巢狀捲動容器的 ref;省略則以視窗為捲動容器 |
className | string | — | 附加樣式(建議在此設定字級與字色) |
細節
- 以
useScroll({ target, container, offset: ["start end", "end start"] })取得目標文字在容器內從進入底部到離開頂部的捲動進度scrollYProgress - 每個字(或詞)依索引分配到
[start, end]的子區間,透過useTransform把進度映射成opacity,逐一由淡灰轉為前景實色 - 逐字模式以字素(grapheme)切割,emoji 與組合字不會被拆壞
- 文字沿用
currentColor(前景色),淡出時自然呈現淺灰;請透過className指定字級與字色
可及性
- 完整文字以
sr-only呈現供輔助科技朗讀,逐字動畫層標記aria-hidden,不會被重複朗讀 - 使用者系統開啟「減少動態效果」時,直接渲染全部前景實色的靜態文字
常見問題
中文可以用 by="word" 嗎?
不建議。逐詞模式是用空白切分,中文句子中間沒有空白,整句會被當成一個單位一次亮起。中文請維持預設的 by="char"。
可以在 Next.js App Router 使用嗎?
可以。原始碼已經有 "use client",在 Server Component 頁面直接 import 即可。「減少動態效果」的靜態版在掛載後才切換,首次渲染與伺服器輸出一致。
高亮從什麼時候開始、什麼時候結束?
捲動進度的範圍是 offset: ["start end", "end start"]:段落頂端碰到可視區底部時開始,段落底端離開可視區頂部時結束,每個字平均分配其中一段,所以最後幾個字會在段落接近畫面頂端時才亮起。
text 可以放粗體或連結嗎?
不行。text 型別是 string,元件會把它切成字或詞再個別上透明度;需要混排樣式時,可以拆成多個元件,或在外層包裝。
螢幕閱讀器會重複讀嗎?
不會。完整文字放在 sr-only 的 span 裡,逐字動畫層標記 aria-hidden。元件執行時只 import motion。