{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "scroll-word-highlight",
 "name": "Wort-für-Wort-Aufhellen beim Scrollen",
 "name_en": "Scroll-linked text highlight / opacity reveal / Scroll-linked text highlight / text opacity reveal",
 "kurz": "Ein Manifest liest sich beim Scrollen selbst vor: Wort für Wort hellt der Absatz von blass auf satt auf.",
 "kategorie": "Schrift-Animationen",
 "kategorie_slug": "schrift-animationen",
 "kategorie_nr": 6,
 "bau_chat": "C1",
 "prioritaet": "A",
 "trendstatus": "etabliert",
 "belegstatus": "belegt",
 "website_belege": 3,
 "stimmung": [
  "ruhig",
  "editorial",
  "warm"
 ],
 "stimmung_roh": [
  "editorial",
  "ruhig",
  "nachdenklich",
  "minimal"
 ],
 "technik": [
  "scrolltrigger",
  "splittext",
  "gsap",
  "scroll-driven-css",
  "framer-motion",
  "vanilla-js"
 ],
 "technik_gruppen": [
  "css",
  "js",
  "gsap",
  "andere"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Ein großer Absatz, meist ein Statement oder Manifest, steht in voller Größe, aber blass da: mit niedriger Deckkraft (0,1 bis 0,4) oder in Grau. Der Text wird in Wörter zerlegt. Der Scrollfortschritt des Absatzes wird auf die Wörter verteilt, jedes Wort hat seinen eigenen Abschnitt. In diesem Abschnitt hellt es auf volle Deckkraft auf. So liest sich der Text im Takt des Scrollens selbst vor.",
  "warum_es_wirkt": "Der Effekt bremst das Lesetempo und macht einen Kernsatz zum Ereignis. Das Scrollen bekommt einen sichtbaren Sinn, ohne dass Inhalt versteckt wird: Der Text ist von Anfang an lesbar. Das wirkt ruhig und klug statt laut.",
  "wann_einsetzen": "Für ein Über-uns-Statement, ein Markenversprechen, eine Mission, ein Zitat oder einen Intro-Absatz. Am besten als einzelner großer Absatz zwischen Bildsektionen.",
  "wann_nicht": "Bei langen Texten, mehreren Absätzen hintereinander und Rechtstexten. Wenn Nutzer schnell scannen oder in eigenem Tempo lesen wollen. Höchstens ein solcher Block pro Seite.",
  "varianten": [
   "Deckkraft blass → voll (Standard, z. B. 0,1 → 1)",
   "Farbe statt Deckkraft: Grau → Textfarbe oder Grau → Akzentfarbe",
   "Textmarker hinter Schlüsselwörtern, der mit dem Lesefortschritt aufzieht",
   "Zeichenweise statt wortweise: feiner, aber teurer",
   "Farbverlauf, der per background-clip: text über den Text läuft",
   "Rein in CSS mit view() und animation-range je Wort über --i"
  ],
  "umsetzung": "GSAP: SplitText.create(p, { type: 'words' }), dann gsap.timeline({ scrollTrigger: { trigger: p, start: 'top bottom-=10%', end: 'bottom center', scrub: true }, defaults: { ease: 'none' } }).fromTo(words, { opacity: 0.1 }, { opacity: 1, stagger: { each: 0.15, ease: 'power1.in' } }). Weil das Ende an der Unterkante hängt, wächst der Bereich mit der Absatzhöhe.\n\nNur CSS: Absatz mit view-timeline-name: --st, Wörter als Spans mit --i und --n. .wort { opacity: .15; animation: lit linear both; animation-timeline: --st; animation-range: cover calc(20% + var(--i) / var(--n) * 40%) cover calc(20% + (var(--i) + 1) / var(--n) * 40%) } @keyframes lit { to { opacity: 1 } }. Wird die Timeline außerhalb des Absatzes gebraucht, hilft timeline-scope.\n\nFallstrick: Der blasse Ausgangszustand hat wenig Kontrast. Er ist dekorativ, der Endzustand muss sicher erreicht werden. Das Ende also nicht zu spät legen, oder Farbe statt Deckkraft animieren.",
  "mobil": "Funktioniert gut. Der Absatz hat mehr Zeilen; hängt das Ende an der Unterkante, wächst der Scrollbereich von selbst mit. Bei festen Bereichen das Fenster anpassen.",
  "reduzierte_bewegung": "Text sofort in voller Farbe zeigen. Ein reiner Farbwechsel ist keine Bewegung und dürfte bleiben; voller Text ist aber die sichere Wahl.",
  "barrierefreiheit": "Der Text steht von Anfang an im DOM. Wort-Spans mit aria-hidden versehen und den ganzen Satz als aria-label auf den Absatz legen, damit Screenreader nicht Wort für Wort stocken (SplitText macht das mit aria: 'auto'). Ausgangskontrast prüfen und nie einen blassen Endzustand riskieren."
 },
 "messwerte": {
  "easing": "none (scrub); Stagger-Verteilung power1.in; expo.out im Scrub (Cohere); none (TFTL)",
  "dauer_ms": "scrollgebunden",
  "stagger_ms": "each 0,15 (relativ zur Timeline); 0,05 relativ (Cohere); sequenziell je Wort (TFTL)",
  "distanz": "opacity 0.1 → 1; Bereich: Oberkante bei 90 % Viewport bis Unterkante bei 50 %; opacity .4 → 1 (Cohere); 0 → 1 (TFTL)",
  "sonstiges": "SplitText type 'words'; Cohere: start 'top 20%', end 'bottom 90%', scrub .5; TFTL: start 'top top', end 'bottom bottom', scrub true",
  "herkunft": "beobachtet",
  "quelle": "https://www.wokine.com/_nuxt/entry.CEQ4-SOz.js; https://cohere.com/_next/static/immutable/chunks/3-s6mh8n2kt5n.js",
  "aus_eintrag": [
   "scroll-word-highlight"
  ]
 },
 "kurve": {
  "bezier": [
   0.11,
   0,
   0.5,
   0
  ],
  "css": "cubic-bezier(0.11, 0, 0.5, 0)",
  "name": "power1.in",
  "dauer_ms": null
 },
 "gesehen_bei": [
  {
   "seite": "Olivier Larose – Text Gradient Scroll Opacity v2",
   "url": "https://blog.olivierlarose.com/tutorials/text-gradient-scroll-opacity-v2",
   "auszeichnung": "",
   "beobachtung": "Tutorial nennt den Effekt als von ‚vielen Awwwards-Websites‘ inspiriert; Framer Motion useScroll mit offset ['start 0.9','start 0.25'], Wort- und Zeichen-Bereiche, Schatten-Ebene darunter.",
   "art": "artikel",
   "weitere_beobachtung": "offset ['start 0.9', 'start 0.25'], Wortbereiche i/N bis (i+1)/N, Zeichen unterteilt, gedimmte Schattenkopie darunter."
  },
  {
   "seite": "Osmo – Highlight Text on Scroll",
   "url": "https://www.osmo.supply/resource/highlight-text-on-scroll",
   "auszeichnung": "",
   "beobachtung": "Als eigene Ressource in der Osmo-Bibliothek gelistet (nur Titel gesehen).",
   "art": "demo"
  },
  {
   "seite": "Codrops Demo „On-Scroll Text Highlight“ (Manoela Ilic)",
   "url": "https://tympanus.net/Development/OnScrollTextHighlight/",
   "auszeichnung": "",
   "beobachtung": "Sammlung von Highlight-Ideen auf Fließtext (Demo geöffnet; Teaser ‚Scroll-based text highlight ideas‘).",
   "art": "demo"
  },
  {
   "seite": "Wokine",
   "url": "https://www.wokine.com/",
   "auszeichnung": "",
   "beobachtung": "Vue-Direktive 'v-reveal' im Bundle (SplitText 3.15.0): Absatz in Wörter gesplittet, opacity 0.1 → 1, ScrollTrigger scrub: true, start 'top bottom-=10%', end 'bottom center', stagger each 0,15 mit ease power1.in, Timeline-Default ease none.",
   "art": "website"
  },
  {
   "seite": "Cohere",
   "url": "https://cohere.com/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft 31.10.2026 (HTML/Bundle per curl abgerufen): Chunk 3-s6mh8n2kt5n.js: GSAP SplitText type 'words', alle Wörter auf opacity .4; ab min-width 768px Timeline mit ScrollTrigger start 'top 20%', end 'bottom 90%', scrub .5: zuerst Element y 150 → 0 (duration 1.5), danach Wörter auf opacity 1 mit ease expo.out, stagger .05, duration 2 (Position '>-1'). Ein zweiter Block nutzt dieselbe Grundhelligkeit .4.",
   "art": "website"
  },
  {
   "seite": "The First The Last",
   "url": "https://www.thefirstthelast.agency/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft 31.10.2026 (HTML/Bundle per curl abgerufen): Nuxt-Chunk DqYuy-ql.js: Titel .main-tags__title per SplitText in Wörter zerlegt; Timeline defaults ease 'none', ScrollTrigger start 'top top', end 'bottom bottom', scrub true; jedes Wort einzeln from opacity 0 nacheinander in die Timeline gehängt.",
   "art": "website"
  }
 ],
 "tutorials": [
  {
   "titel": "Text Gradient Scroll Opacity v2 (Olivier Larose)",
   "url": "https://blog.olivierlarose.com/tutorials/text-gradient-scroll-opacity-v2"
  },
  {
   "titel": "Text Gradient Opacity On Scroll (Olivier Larose)",
   "url": "https://blog.olivierlarose.com/tutorials/text-gradient-opacity-on-scroll"
  },
  {
   "titel": "Chrome – Scroll-driven Animations",
   "url": "https://developer.chrome.com/docs/css-ui/scroll-driven-animations"
  }
 ],
 "kombinierbar_mit": [
  "split-mask-reveal",
  "marquee-laufband",
  "pinned-scrub-scrollytelling",
  "theme-farbwechsel-scroll"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/schrift-animationen/scroll-word-highlight/",
  "meta": "https://cecodesign.de/lab/fundus/schrift-animationen/scroll-word-highlight/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/schrift-animationen/scroll-word-highlight/demo"
 },
 "herkunft": {
  "quelldateien": [
   "schriftanimation.json",
   "scroll.json",
   "patch-belege-1.json",
   "r3-belege-a.json"
  ],
  "pruefnotizen": [
   "patch-belege-1.json: Nur 1 Produktionsbeleg gefunden (Ziel 2). Lando Norris hat einen [data-text-highlight]-Hook im Bundle, Implementierung aber nicht auffindbar – nicht gezählt.",
   "r3-belege-a.json (Runde 3, 31.10.2026): Cohere liegt mit Grundopazität .4 deutlich heller als Wokine (.1) – lesbar auch ohne Scroll. TFTL startet bei 0, also echtes Einblenden statt Aufhellen."
  ],
  "zusammengelegt_aus": [
   "scroll-word-highlight",
   "text-scroll-highlight"
  ],
  "querverweis_kategorien": [
   "Scroll & Section-Animationen"
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Ein Manifest liest sich beim Scrollen selbst vor: Wort für Wort hellt der Absatz von blass auf satt auf.",
  "demo": true,
  "abhaengigkeiten": [
   "gsap@3.15.0",
   "ScrollTrigger@3.15.0",
   "SplitText@3.15.0"
  ],
  "werte": {
   "split": "SplitText type 'words', aria 'auto'",
   "scrolltrigger": "start 'top bottom-=10%', end 'bottom center' (Oberkante bei 90 % Viewport bis Unterkante bei 50 %)",
   "deckkraft": "opacity 0.1 → 1, duration 0.5 je Wort, ease 'none', stagger { each: 0.15, ease: 'power1.in' }, scrub true (Wokine)",
   "farbe": "color #c4bbad → #1b1814 auf Grund #f2eee7, sonst wie Deckkraft (opacity bleibt 1)",
   "marker": "opacity 0.4 → 1, duration 2 je Wort, ease 'expo.out', stagger each 0.05, scrub 0.5 (Cohere); Textmarker background-size 0% → 100% × 0.38em, Position 0 86 %, duration 1, expo.out, Start mit dem ersten Wort des Schlüsselbegriffs, box-decoration-break: clone",
   "kurve_verteilung": "power1.in = cubic-bezier(0.11, 0, 0.5, 0)",
   "typo": "Instrument Sans 500, clamp(27px, 3.9vw, 60px), line-height 1.1, letter-spacing -0.032em, max-width 21.5em; Akzent Instrument Serif Italic",
   "vorfuehrung": "Fortschritt 0 → 1 in 4,8 s linear, 1,4 s halten, 0,5 s ausblenden, nächste Variante"
  },
  "ausloeser": "scroll",
  "touch": "Gleiches Verhalten per Wischen; der Absatz ist höher, der Bereich wächst mit, weil das Ende an der Unterkante hängt. Werte-Leiste kompakt (zwei Werte plus Wortzähler).",
  "reduziert": "Text steht sofort in voller Farbe, kein Scroll-Bezug. In der Variante Marker sind die Markierungen statisch sichtbar.",
  "korrekturen": {
   "beschreibung": "Ein großer Absatz, meist ein Statement oder Manifest, steht in voller Größe, aber blass da: mit niedriger Deckkraft (0,1 bis 0,4) oder in Grau. Der Text wird in Wörter zerlegt. Der Scrollfortschritt des Absatzes wird auf die Wörter verteilt, jedes Wort hat seinen eigenen Abschnitt. In diesem Abschnitt hellt es auf volle Deckkraft auf. So liest sich der Text im Takt des Scrollens selbst vor.",
   "warum_es_wirkt": "Der Effekt bremst das Lesetempo und macht einen Kernsatz zum Ereignis. Das Scrollen bekommt einen sichtbaren Sinn, ohne dass Inhalt versteckt wird: Der Text ist von Anfang an lesbar. Das wirkt ruhig und klug statt laut.",
   "wann_einsetzen": "Für ein Über-uns-Statement, ein Markenversprechen, eine Mission, ein Zitat oder einen Intro-Absatz. Am besten als einzelner großer Absatz zwischen Bildsektionen.",
   "wann_nicht": "Bei langen Texten, mehreren Absätzen hintereinander und Rechtstexten. Wenn Nutzer schnell scannen oder in eigenem Tempo lesen wollen. Höchstens ein solcher Block pro Seite.",
   "varianten": [
    "Deckkraft blass → voll (Standard, z. B. 0,1 → 1)",
    "Farbe statt Deckkraft: Grau → Textfarbe oder Grau → Akzentfarbe",
    "Textmarker hinter Schlüsselwörtern, der mit dem Lesefortschritt aufzieht",
    "Zeichenweise statt wortweise: feiner, aber teurer",
    "Farbverlauf, der per background-clip: text über den Text läuft",
    "Rein in CSS mit view() und animation-range je Wort über --i"
   ],
   "umsetzung": "GSAP: SplitText.create(p, { type: 'words' }), dann gsap.timeline({ scrollTrigger: { trigger: p, start: 'top bottom-=10%', end: 'bottom center', scrub: true }, defaults: { ease: 'none' } }).fromTo(words, { opacity: 0.1 }, { opacity: 1, stagger: { each: 0.15, ease: 'power1.in' } }). Weil das Ende an der Unterkante hängt, wächst der Bereich mit der Absatzhöhe.\n\nNur CSS: Absatz mit view-timeline-name: --st, Wörter als Spans mit --i und --n. .wort { opacity: .15; animation: lit linear both; animation-timeline: --st; animation-range: cover calc(20% + var(--i) / var(--n) * 40%) cover calc(20% + (var(--i) + 1) / var(--n) * 40%) } @keyframes lit { to { opacity: 1 } }. Wird die Timeline außerhalb des Absatzes gebraucht, hilft timeline-scope.\n\nFallstrick: Der blasse Ausgangszustand hat wenig Kontrast. Er ist dekorativ, der Endzustand muss sicher erreicht werden. Das Ende also nicht zu spät legen, oder Farbe statt Deckkraft animieren.",
   "mobil": "Funktioniert gut. Der Absatz hat mehr Zeilen; hängt das Ende an der Unterkante, wächst der Scrollbereich von selbst mit. Bei festen Bereichen das Fenster anpassen.",
   "reduzierte_bewegung": "Text sofort in voller Farbe zeigen. Ein reiner Farbwechsel ist keine Bewegung und dürfte bleiben; voller Text ist aber die sichere Wahl.",
   "barrierefreiheit": "Der Text steht von Anfang an im DOM. Wort-Spans mit aria-hidden versehen und den ganzen Satz als aria-label auf den Absatz legen, damit Screenreader nicht Wort für Wort stocken (SplitText macht das mit aria: 'auto'). Ausgangskontrast prüfen und nie einen blassen Endzustand riskieren."
  },
  "geprueft": "31.10.2026",
  "notiz": "Demo: Manifest des erfundenen Kölner Studios Feldmark, mit Wortmarke darüber und zwei Arbeiten darunter. Drei Varianten: Deckkraft und Farbe mit den Wokine-Werten, Marker mit den Cohere-Werten (Grundhelligkeit 0,4) plus Textmarker unter drei Schlüsselbegriffen. Die Startzeiten der Wörter werden wie stagger { each, ease } berechnet und einzeln gesetzt, damit die Werte-Leiste einen Wortzähler zeigen kann. Die Vorführung simuliert den Scrollfortschritt und wechselt die Varianten; eigenes Scrollen übernimmt wieder. Bilder 01.11.2026: eigene Bilder statt Portfolio. Zugang 02.11.2026: --leise Alpha .56 auf .64 (5:1), Wortmarke clamp-Minimum 76 auf 48 px und darf bei engem Platz umbrechen (kein Querscrollen bei 320 px und bei Textabständen 1.4.12), Knopfrahmen im Kontrastmodus. Offen: gedimmte Wörter vor der Lesefront sind der Effekt selbst (Absatz hat aria-label)."
 }
}
