scroll-effects
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSkill: scroll-effects
Skill: scroll-effects
Hub hiệu ứng cuộn trang: 64 bản gốc nguyên văn (freefrontend/CodePen, MIT) ở — duyệt gallery, copy nguyên file. Kèm 7 hiệu ứng vanilla tự viết trong cho dự án không được kéo lib ngoài.
Rheinmir/uiux-assetassets/页面滚动效果中心:64 份逐字保留的原版(freefrontend/CodePen,MIT)位于 ——可浏览 gallery 并完整复制文件。另附 7 种在 中自行编写的 vanilla 效果,供不允许引入外部 lib 的项目使用。
Rheinmir/uiux-assetassets/WHAT
WHAT
Purpose và context
目的与上下文
- Purpose: gắn hiệu ứng cuộn trang nhẹ vào trang đích — mặc định copy nguyên file bản GỐC từ ; dự án không được kéo lib ngoài thì dùng 7 pattern vanilla trong
Rheinmir/uiux-asset.assets/ - Trigger (when to use):
- Trang cần hiệu ứng hiện-dần khi cuộn, chữ stagger, highlight dẫn mắt, nav co lại, nút về đầu trang, mục lục bám theo section, hoặc parallax nhẹ.
- User nói "hiệu ứng scroll", "scroll to top", "scrollspy", "parallax", "reveal khi cuộn".
- Non-goals: KHÔNG dùng cho: chuyển ảnh điện ảnh nặng GPU (đó là ), trục timeline mốc thời gian (đó là
blur), cuộn ngang pin-section kiểu GSAP ScrollTrigger phức tạp (vượt phạm vi skill nhẹ này — nói rõ với user).timeline
- **目的:**为目标页面添加轻量滚动效果——默认从 完整复制原版文件;如果项目不允许引入外部 lib,则使用
Rheinmir/uiux-asset中的 7 种 vanilla pattern。assets/ - 触发条件(何时使用):
- 页面需要滚动渐显、staggered text、引导视线的高亮、收缩式 nav、返回顶部按钮、跟随 section 的目录,或轻量 parallax。
- 用户说“滚动效果”“scroll to top”“scrollspy”“parallax”“滚动时 reveal”。
- **非目标:**不适用于:重度 GPU 图像过渡(即 )、时间轴(即
blur),以及类似 GSAP ScrollTrigger 的复杂横向滚动 pin-section(超出此轻量 skill 的范围——应向用户明确说明)。timeline
Mental model
心智模型
nhu cầu hiệu ứng → gallery 64 bản gốc (mặc định, copy nguyên file) hoặc 7 pattern vanilla (không được kéo lib) → adapt token theo design.md → một IntersectionObserver + một scroll listener rAF → reduced-motion tắt hết → verify playwright效果需求 → 64 份原版组成的 gallery(默认,完整复制文件)或 7 种 vanilla pattern(不允许引入 lib)→ 根据 design.md 适配 token → 使用一个 IntersectionObserver + 一个经 rAF 节流的 scroll listener → reduced-motion 下全部关闭 → 使用 playwright 验证Input và output contract
输入与输出约定
| Field | Required? | Ý nghĩa | |
|---|---|---|---|
| In | hiệu ứng cần | có | một trong 7 pattern hoặc mục gallery |
| In | ràng buộc dự án | không | có được kéo lib/file ngoài không; có |
| Out | file hiệu ứng trong dự án | có | bản gốc copy nguyên (giữ comment ghi công dòng đầu) hoặc asset vanilla đã adapt |
| Out | bằng chứng verify | có | ảnh trước/sau cuộn, |
| 字段 | 必填? | 含义 | |
|---|---|---|---|
| In | 所需效果 | 是 | 7 种 pattern 之一或 gallery 条目 |
| In | 项目约束 | 否 | 是否允许引入外部 lib/file;是否有 |
| Out | 项目中的效果文件 | 是 | 完整复制的原版(保留首行署名 comment)或已适配的 vanilla asset |
| Out | 验证证据 | 是 | 滚动前后截图、 |
Rules và capabilities
规则与能力
- RULE-01 (MUST): → tắt toàn bộ: CSS ép
prefers-reduced-motion: reducehiện ngay không transition, JS bỏ smooth scroll và parallax (đã code sẵn trong assets, đừng xoá nhánh này khi adapt)..is-in - RULE-02 (MUST): Một dùng chung cho reveal + stagger + highlight + TOC (đã gộp trong
IntersectionObserver) — đừng tạo 4 observer riêng.scroll-effects.js - RULE-03 (MUST): Scroll listener duy nhất, rAF-throttle — nav + top + parallax đọc chung một mỗi frame, không gắn 3 listener
scrollYrời.scroll - RULE-04 (MUST): Verify bằng : chụp trước/sau cuộn, assert
playwright-verifyxuất hiện, đo không có horizontal overflow do parallax..is-in - RULE-05 (MUST): Khi adapt vào dự án có : đổi token màu/spacing, giữ nguyên tên
design.md(JS bám vào chúng).data-se-* - Capabilities: đọc gallery/repo asset ngoài (mạng) hoặc asset nội bộ; ghi file front-end dự án; chạy trình duyệt headless qua HTTP local.
- RULE-01(必须):→ 关闭所有效果:CSS 强制
prefers-reduced-motion: reduce立即显示且不使用 transition,JS 移除 smooth scroll 和 parallax(相关分支已写入 assets,适配时不要删除)。.is-in - RULE-02(必须):使用一个共享的 处理 reveal + stagger + highlight + TOC(已在
IntersectionObserver中合并)——不要创建 4 个独立 observer。scroll-effects.js - RULE-03(必须):只使用一个经 rAF 节流的 scroll listener——nav + top + parallax 每帧共同读取同一个 ,不要绑定 3 个独立的
scrollYlistener。scroll - RULE-04(必须):使用 验证:截取滚动前后的画面,断言
playwright-verify出现,并测量 parallax 未造成 horizontal overflow。.is-in - RULE-05(必须):适配到包含 的项目时:修改颜色/spacing token,同时保留
design.md名称(JS 依赖这些属性)。data-se-* - 能力:读取 gallery/外部 repo asset(网络)或内部 asset;写入项目的 front-end 文件;通过本地 HTTP 运行 headless 浏览器。
Failure boundaries
失败边界
- Yêu cầu là WebGL nặng, timeline mốc, hoặc pin-section GSAP phức tạp → blocked ngoài phạm vi, nói rõ với user và chỉ skill đúng.
- Không truy cập được gallery/repo ngoài hoặc dự án cấm lib ngoài → dùng 7 pattern vanilla (không phải lỗi).
- Verify playwright không thấy hoặc có horizontal overflow → failed, sửa rồi verify lại.
.is-in
- 需求涉及重度 WebGL、时间轴或复杂的 GSAP pin-section → blocked,属于范围外;向用户明确说明,并只使用对应的 skill。
- 无法访问外部 gallery/repo,或项目禁止引入外部 lib → 使用 7 种 vanilla pattern(这不是错误)。
- Playwright 验证未发现 ,或存在 horizontal overflow → failed;修复后重新验证。
.is-in
HOW
HOW
Main workflow
主工作流
| Step | Type | Inputs | Action | Outputs/exit | Failure/next |
|---|---|---|---|---|---|
| W01 | judgment | yêu cầu | Khớp phạm vi (không phải blur/timeline/GSAP pin) | hiệu ứng trong phạm vi | ngoài phạm vi → blocked |
| W02 | judgment | ràng buộc dự án | Chọn nguồn: bản gốc gallery (mặc định) hay vanilla | nguồn | — |
| W03 | effect | nguồn | Bản gốc: mở link chạy → copy nguyên | file trong dự án | — |
| W04 | effect | | Adapt token màu/spacing, giữ | file đã adapt | — |
| W05 | deterministic | trang qua HTTP | | PASS | FAIL → sửa, lặp W05 |
Chi tiết từng bước (nguồn chân lý cho W01–W05):
| 步骤 | 类型 | 输入 | 操作 | 输出/退出 | 失败/下一步 |
|---|---|---|---|---|---|
| W01 | 判断 | 需求 | 判断范围是否匹配(不是 blur/timeline/GSAP pin) | 范围内的效果 | 超出范围 → blocked |
| W02 | 判断 | 项目约束 | 选择来源:原版 gallery(默认)或 vanilla | 来源 | — |
| W03 | 效果 | 来源 | 原版:打开可运行链接 → 完整复制 | 项目中的文件 | — |
| W04 | 效果 | | 适配颜色/spacing token,保留 | 已适配的文件 | — |
| W05 | 确定性 | 通过 HTTP 访问的页面 | | PASS | FAIL → 修复并重复 W05 |
以下为每个步骤的详细信息(W01–W05 的依据来源):
Bản gốc — dùng TRƯỚC (copy nguyên file, đừng viết lại)
原版——优先使用(完整复制文件,不要重写)
Code gốc NGUYÊN VĂN của tác giả (CodePen public = MIT) nằm ở repo ngoài — gallery chạy thật: https://rheinmir.github.io/uiux-asset/scroll-effects/ .
Quy trình: mở link chạy để xem đúng hiệu ứng → copy nguyên file (+ thư mục nếu file trỏ tới) vào dự án → giữ comment ghi công dòng đầu → chỉ sửa nội dung/ảnh/màu. Chạy local qua HTTP, không .
nếu cần cả bộ offline.
Rheinmir/uiux-asset.html_assets/file://git clone --depth 1 https://github.com/Rheinmir/uiux-assetHub: duyệt cả 64 mục ở gallery (lọc theo tên/kỹ thuật/tác giả), rồi rẽ sang skill con tương ứng.
assets/作者的原版代码逐字保留(CodePen public = MIT),位于外部 repo ——可通过实际运行的 gallery 访问:https://rheinmir.github.io/uiux-asset/scroll-effects/ 。
流程:打开可运行链接以查看准确效果 → 将 文件完整复制到项目中(如果文件引用了 ,也复制该目录)→ 保留首行署名 comment → 只修改内容、图片和颜色。通过 HTTP 在本地运行,不要使用 。
如需完整的离线版本,可执行:
Rheinmir/uiux-asset.html_assets/file://git clone --depth 1 https://github.com/Rheinmir/uiux-assetHub:浏览 gallery 中的全部 64 个条目(可按名称、技术或作者筛选),然后转入相应的子 skill。
此 skill 中的 只是自行编写的精简版 vanilla 实现——仅在项目不允许引入外部 lib 时使用;默认使用上述原版。
assets/Assets
Assets
assets/demo.htmlassets/scroll-effects.cssassets/scroll-effects.jsdesign.mdassets/demo.htmlassets/scroll-effects.cssassets/scroll-effects.jsdesign.mdBranches
分支
| ID | Kind | Guard | Hành vi | Skip / failure | Rejoin |
|---|---|---|---|---|---|
| B01 | conditional_required | dự án KHÔNG được kéo lib/file ngoài | dùng 7 pattern vanilla trong | được kéo ngoài → bản gốc gallery | W04 |
| B02 | user_optional | cần cả bộ gốc offline | | — | W03 |
| B03 | conditional_required | mục gallery thuộc một skill con | rẽ sang skill con tương ứng | — | kết thúc ở skill con |
| ID | 类型 | 条件 | 行为 | 跳过/失败 | 汇合点 |
|---|---|---|---|---|---|
| B01 | 必需条件分支 | 项目不允许引入外部 lib/file | 使用 | 允许引入外部内容 → 使用 gallery 原版 | W04 |
| B02 | 用户可选 | 需要完整的离线原版集合 | 执行 | — | W03 |
| B03 | 必需条件分支 | gallery 条目属于某个子 skill | 转入相应的子 skill | — | 在子 skill 中结束 |
Validation và stopping
验证与停止条件
Chạy qua HTTP local (không ). PASS khi playwright chụp trước/sau cuộn thấy , không horizontal overflow, và với reduced-motion mọi phần tử hiện ngay. Dừng khi PASS; FAIL thì sửa và verify lại.
file://.is-in通过本地 HTTP 运行(不要使用 )。当 Playwright 截取的滚动前后画面显示 、不存在 horizontal overflow,并且 reduced-motion 模式下所有元素立即显示时,判定为 PASS。PASS 后停止;FAIL 则修复并重新验证。
file://.is-inExamples
示例
- Positive: "thêm scroll to top + scrollspy cho trang docs, không được kéo lib" → B01 dùng +
[data-se-top]từ[data-se-toc], đổi token theoassets/, giữdesign.md→ playwright: nút hiện khidata-se-*, link TOC nhậnscrollY > innerHeight..is-active - Boundary/failure: "làm section cuộn ngang pin kiểu GSAP" → ngoài phạm vi skill nhẹ này → nói rõ với user, không cố dựng bằng parallax .
data-se-parallax
- 正向:“为文档页添加 scroll to top + scrollspy,不允许引入 lib” → B01 使用 中的
assets/+[data-se-top],根据[data-se-toc]修改 token,保留design.md→ Playwright:滚动超过data-se-*后按钮出现,目录链接获得innerHeight。.is-active - 边界/失败:“实现类似 GSAP 的横向滚动 pin section” → 超出此轻量 skill 的范围 → 向用户明确说明,不要尝试使用 parallax 强行实现。
data-se-parallax
Reference — 7 pattern (markup tối thiểu + cơ chế)
参考——7 种 pattern(最小 markup + 实现机制)
1. Reveal on scroll — [data-se-reveal]
[data-se-reveal]1. Reveal on scroll — [data-se-reveal]
[data-se-reveal]Phần tử mờ + trượt nhẹ, hiện khi cuộn vào khung nhìn.
html
<div data-se-reveal>Lộ dần khi cuộn tới</div>IntersectionObserver.is-inopacity/translateY元素淡入并轻微位移,在滚动进入视口时显示。
html
<div data-se-reveal>Lộ dần khi cuộn tới</div>IntersectionObserver.is-inopacity/translateY2. Staggered text — [data-se-stagger]
[data-se-stagger]2. Staggered text — [data-se-stagger]
[data-se-stagger]Các dòng chữ hiện nối tiếp nhau.
html
<h2 data-se-stagger>
<span>Dòng một</span><span>Dòng hai</span><span>Dòng ba</span>
</h2>JS gán cho mỗi → CSS . Chỉ tách theo phần tử con có sẵn, không tự split text node (giữ DOM đơn giản, tránh lỗi a11y).
--ispantransition-delay: calc(var(--i) * 90ms)各行文字依次出现。
html
<h2 data-se-stagger>
<span>Dòng một</span><span>Dòng hai</span><span>Dòng ba</span>
</h2>JS 为每个 分配 → CSS 。仅根据已有的子元素进行拆分,不要自动拆分 text node(保持 DOM 简单,避免 a11y 问题)。
span--itransition-delay: calc(var(--i) * 90ms)3. Scroll highlight — [data-se-highlight] > mark
[data-se-highlight] > mark3. Scroll highlight — [data-se-highlight] > mark
[data-se-highlight] > markĐánh dấu ý chính, vệt màu quét trái→phải khi đoạn văn vào khung nhìn.
html
<p data-se-highlight>Đọc tới đây <mark>ý chính hiện ra</mark> rồi đọc tiếp.</p>markbackground-size: 0% → 100%.is-in<mark>突出关键观点;当段落进入视口时,色带从左向右扫过。
html
<p data-se-highlight>Đọc tới đây <mark>ý chính hiện ra</mark> rồi đọc tiếp.</p>当父元素获得 时, 的 从 0% 过渡到 100%。使用具有真实语义的 ,不要用 代替。
.is-inmarkbackground-size<mark>span4. Sticky shrink nav — [data-se-nav]
[data-se-nav]4. Sticky shrink nav — [data-se-nav]
[data-se-nav]Header co gọn khi cuộn xuống, phồng lại khi về đầu.
html
<header data-se-nav class="site-nav">…</header>Scroll listener (rAF-throttle) toggle khi . Chỉ đổi padding/font-size qua class, không set style inline từng frame.
.is-shrunkscrollY > 24向下滚动时 header 收缩,回到顶部时重新展开。
html
<header data-se-nav class="site-nav">…</header>经 rAF 节流的 scroll listener 在 时切换 。仅通过 class 修改 padding/font-size,不要每帧设置 inline style。
scrollY > 24.is-shrunk5. Scroll to top — [data-se-top]
[data-se-top]5. Scroll to top — [data-se-top]
[data-se-top]Nút về đầu trang, chỉ hiện sau khi cuộn qua một màn hình.
html
<button data-se-top aria-label="Về đầu trang">↑</button>Click → (trừ khi → ). Ngưỡng hiện: .
window.scrollTo({ top: 0, behavior: "smooth" })prefers-reduced-motion"auto"scrollY > innerHeight返回顶部按钮,仅在滚动超过一屏后显示。
html
<button data-se-top aria-label="Về đầu trang">↑</button>点击 → (如果启用 ,则使用 )。显示阈值:。
window.scrollTo({ top: 0, behavior: "smooth" })prefers-reduced-motion"auto"scrollY > innerHeight6. Scrollspy TOC — [data-se-toc] a[href^="#"]
+ section[id]
[data-se-toc] a[href^="#"]section[id]6. Scrollspy TOC — [data-se-toc] a[href^="#"]
+ section[id]
[data-se-toc] a[href^="#"]section[id]Mục lục sticky, link sáng theo section đang đọc.
html
<nav data-se-toc><a href="#s1">Mục 1</a><a href="#s2">Mục 2</a></nav>
<section id="s1">…</section><section id="s2">…</section>IntersectionObserverrootMargin: "-40% 0px -55% 0px".is-activesticky 目录,链接根据当前阅读的 section 高亮。
html
<nav data-se-toc><a href="#s1">Mục 1</a><a href="#s2">Mục 2</a></nav>
<section id="s1">…</section><section id="s2">…</section>IntersectionObserverrootMargin: "-40% 0px -55% 0px".is-active7. Parallax nhẹ — [data-se-parallax="0.2"]
[data-se-parallax="0.2"]7. 轻量 Parallax — [data-se-parallax="0.2"]
[data-se-parallax="0.2"]Lớp nội dung trôi chậm hơn/nhanh hơn tốc độ cuộn.
html
<div data-se-parallax="0.15">Trôi chậm tạo chiều sâu</div>rAF loop: . Giá trị khuyến nghị ; vượt quá gây say chuyển động. KHÔNG dùng cho chữ nhỏ cần đọc chính xác.
translateY = (elCenter - viewportCenter) * speedspeed|v| ≤ 0.3内容层以比滚动速度更慢或更快的速度移动。
html
<div data-se-parallax="0.15">Trôi chậm tạo chiều sâu</div>rAF loop:。建议 ;超过该值可能引发晕动症。不要用于需要精确阅读的小字号文字。
translateY = (elCenter - viewportCenter) * speed|v| ≤ 0.3Origin
来源
- User chốt "làm đi hỏi nhiều quá" → thay vì bulk-copy 81 tác phẩm, viết BỘ GỐC 7 pattern generic (kỹ thuật chuẩn ngành: IntersectionObserver/scroll listener/rAF — không phải biểu đạt sáng tạo riêng của ai) để downstream tham khảo code mẫu ngay, đúng cách /
blurđã làm.timeline
- 用户最终决定“直接做,别问太多” → 因此没有批量复制 81 个作品,而是编写了由 7 个通用 pattern 构成的原版集合(采用行业标准技术:IntersectionObserver/scroll listener/rAF——并非任何人的独创创意表达),供 downstream 立即参考示例代码,做法与现有 /
blurskill 一致。timeline