Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Reveal marked-up text word by word as scroll progress advances, while preserving semantic inline links, emphasis, responsive line wrapping, and reduced-motion readability. Use for headlines, quotes, manifestos, product statements, onboarding messages, or editorial passages where scrolling should pace comprehension rather than simulate typing.
.claude/skills/mengto-scroll-scrubbed-word-reveal/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 12% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 14% | 0% |
| case-06 | ✗→✓ | ▲ Improved | -27% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 19% | 0% |
| case-13 | ✗→✓ | ▲ Improved | -6% | 0% |
Make reading progress visible without replacing real text, breaking inline markup, or depending on a fixed line count.
TreeWalker; do not flatten the container with textContent or innerHTML.script, style, form controls, and elements marked with [data-no-split].aria-hidden="true" only when an equivalent unsplit accessible copy remains available.Preferred structure:
html<p class="reveal" data-reveal> Motion should <em>explain</em> the next state, not decorate it. </p>
Avoid line-based splitting. Browser line wraps must remain free to change with container width, language, zoom, and font loading.
Use section progress as the single source of truth:
jsconst reveal = Math.min(1, Math.max(0, progress)); const local = Math.min(1, Math.max(0, reveal * wordCount - index)); word.style.setProperty("--word-progress", local);
Interpolate hidden opacity, blur, and vertical offset from --word-progress. Keep the visible state identical to normal typography.
Use GSAP ScrollTrigger with scrub when precise starts, ends, refresh, or a shared timeline is needed. Use a dependency-free scroll measurement plus requestAnimationFrame for a standalone section.
0.12–0.34–10px0.08–0.22em120–220% of the viewport for a paragraph10–30%Expose the values as CSS custom properties. Scale the scroll span from text length rather than assuming one duration fits every passage.
strong, em, marks, and accent spans keep their semantics and styling.prefers-reduced-motion: reduce, show every word immediately, remove blur and transforms, and remove any pinning.Kill ScrollTriggers, remove scroll and resize listeners, cancel animation frames, and restore the original marked-up subtree on route change or component unmount. Refresh measurements after fonts load if start or end positions depend on text geometry.
Test inline links and emphasis, punctuation, repeated spaces, long words, 200% zoom, 390/768/1440 widths, content changes, forward and reverse scrolling, reduced motion, keyboard focus, screen-reader reading order, and teardown. The final DOM must still communicate the complete sentence with JavaScript disabled.
Use demo/index.html as the working reference and demo/PROMPT.md to recreate or remix it. Keep REFERENCES.md as the links-only implementation source list.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 20,355 | 27,538 | +35% | 1 | 1 | 0% | 4,206 | 7,089 | +69% | 0 | 0 | — |
case-02 | fail→fail | 20,766 | 19,577 | -6% | 1 | 1 | 0% | 4,237 | 5,001 | +18% | 0 | 0 | — |
case-03 | fail→pass | 20,082 | 18,390 | -8% | 1 | 1 | 0% | 4,187 | 4,694 | +12% | 0 | 0 | — |
case-04 | pass→pass | 13,044 | 15,881 | +22% | 1 | 1 | 0% | 2,498 | 3,339 | +34% | 0 | 0 | — |
case-05 | fail→pass | 13,573 | 10,737 | -21% | 1 | 1 | 0% | 2,804 | 3,199 | +14% | 0 | 0 | — |
case-06 | fail→pass | 24,967 | 3,774 | -85% | 1 | 1 | 0% | 2,343 | 1,713 | -27% | 0 | 0 | — |
case-07 | pass→pass | 12,456 | 7,670 | -38% | 1 | 1 | 0% | 2,263 | 2,243 | -1% | 0 | 0 | — |
case-08 | pass→pass | 12,078 | 6,799 | -44% | 1 | 1 | 0% | 2,202 | 2,127 | -3% | 0 | 0 | — |
case-09 | pass→pass | 16,620 | 9,051 | -46% | 1 | 1 | 0% | 2,845 | 2,581 | -9% | 0 | 0 | — |
case-10 | pass→pass | 13,237 | 11,321 | -14% | 1 | 1 | 0% | 2,460 | 2,974 | +21% | 0 | 0 | — |
case-11 | fail→pass | 15,107 | 12,292 | -19% | 1 | 1 | 0% | 2,709 | 3,213 | +19% | 0 | 0 | — |
case-12 | pass→pass | 14,542 | 8,773 | -40% | 1 | 1 | 0% | 2,492 | 2,500 | +0% | 0 | 0 | — |
case-13 | fail→pass | 13,270 | 6,662 | -50% | 1 | 1 | 0% | 2,259 | 2,131 | -6% | 0 | 0 | — |
case-14 | pass→pass | 14,830 | 13,863 | -7% | 1 | 1 | 0% | 2,942 | 3,719 | +26% | 0 | 0 | — |
case-15 | fail→pass | 12,512 | 8,733 | -30% | 1 | 1 | 0% | 2,236 | 2,543 | +14% | 0 | 0 | — |
case-16 | pass→pass | 11,367 | 4,834 | -57% | 1 | 1 | 0% | 1,936 | 1,682 | -13% | 0 | 0 | — |
case-17 | fail→pass | 10,969 | 2,073 | -81% | 1 | 1 | 0% | 2,033 | 1,257 | -38% | 0 | 0 | — |
case-18 | fail→fail | 16,341 | 12,133 | -26% | 1 | 1 | 0% | 3,401 | 3,342 | -2% | 0 | 0 | — |
case-19 | pass→pass | 10,624 | 11,870 | +12% | 1 | 1 | 0% | 2,225 | 3,414 | +53% | 0 | 0 | — |
case-20 | pass→fail | 11,125 | 11,224 | +1% | 1 | 1 | 0% | 2,188 | 3,152 | +44% | 0 | 0 | — |
case-21 | pass→pass | 13,877 | 16,070 | +16% | 1 | 1 | 0% | 2,832 | 4,142 | +46% | 0 | 0 | — |
case-22 | pass→pass | 13,084 | 18,301 | +40% | 1 | 1 | 0% | 2,795 | 4,876 | +74% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +27 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.