{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "scroll-fortschritt",
 "name": "Scroll-Fortschrittsbalken und -ring",
 "name_en": "Scroll progress indicator / Scroll progress indicator / chapter index",
 "kurz": "Magazinartikel des erfundenen Tidehaus Flensburg: Lesebalken unter der Kopfzeile, Ring um den Nach-oben-Knopf oder Fortschritt je Kapitel, alles rein in CSS an den Scroll gekoppelt.",
 "kategorie": "Mikroanimationen",
 "kategorie_slug": "mikroanimationen",
 "kategorie_nr": 9,
 "bau_chat": "C4",
 "prioritaet": "B",
 "trendstatus": "etabliert",
 "belegstatus": "teilbelegt",
 "website_belege": 1,
 "stimmung": [
  "ruhig",
  "editorial",
  "präzise"
 ],
 "stimmung_roh": [
  "ruhig",
  "funktional",
  "technisch",
  "präzise",
  "editorial"
 ],
 "technik": [
  "scroll-driven-css",
  "css",
  "svg"
 ],
 "technik_gruppen": [
  "css",
  "canvas"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Ein schmaler Balken oben oder ein Ring wächst mit dem Scrollfortschritt. In CSS reicht animation-timeline: scroll() mit scaleX von 0 nach 1 und transform-origin links. Ohne Unterstützung übernimmt ein kleiner Scroll-Listener, bei rein dekorativem Zweck lässt man den Balken weg. Die ausführliche Fassung mit Kapitelanzeige steht unter fortschritt-kapitelanzeige.",
  "warum_es_wirkt": "Leser sehen, wie weit sie in einem langen Artikel oder einer Case Study sind und wie viel noch kommt. Das senkt die Hürde, weiterzulesen. Nebenbei ist der Balken ein präzises grafisches Detail, das den Rahmen der Seite lebendig macht.",
  "wann_einsetzen": "Lange Artikel, Case Studies, Dokumentationen und lange Landingpages. Außerdem gepinnte Scrollytelling-Strecken und horizontale Sections, bei denen man sonst die Orientierung verliert.",
  "wann_nicht": "Auf kurzen Seiten. Wenn eine Scrollspy-Navigation den Fortschritt schon zeigt. Als reine Dekoration ohne Orientierungsnutzen.",
  "varianten": [
   "Lesebalken oben: scaleX über scroll(root)",
   "Ring um den Nach-oben-Knopf: SVG stroke-dashoffset oder conic-gradient mit scroll-timeline",
   "Fortschritt je Abschnitt: view-timeline je Section, mit timeline-scope für den fixen Balken",
   "Kapitelnavigation mit aktivem Zustand: IntersectionObserver oder scroll-state, aria-current",
   "Kleiner Prozentzähler 00–100 als typografisches Element über @property und counter()",
   "Schrittanzeige im Karussell: ::scroll-marker und ::scroll-marker-group",
   "JS-Fortschrittsbalken (z. B. mit Motion), wenn CSS nicht reicht"
  ],
  "umsetzung": "@media (prefers-reduced-motion: no-preference) { @supports (animation-timeline: scroll()) { @keyframes grow { from { transform: scaleX(0) } to { transform: scaleX(1) } } #progress { position: fixed; inset: 0 0 auto 0; block-size: 3px; background: var(--accent); transform-origin: 0 50%; animation: grow auto linear; animation-timeline: scroll() } } } <div id='progress' aria-hidden='true'></div>\n\nanimation-timeline immer nach dem Shorthand animation deklarieren, sonst wird sie zurückgesetzt. Kurzform mit scale: @keyframes grow { from { scale: 0 1 } } und animation-timeline: scroll(root block). Fortschritt je Section: benannte view-timeline auf der Section, timeline-scope auf body, damit der fixe Balken sie referenzieren kann; animation-range: contain 0% contain 100%. Prozentzahl: @property --p { syntax: '<integer>'; inherits: false; initial-value: 0 } animieren und per counter() ausgeben. Einen Polyfill empfiehlt Chrome nicht.",
  "mobil": "Verhält sich wie auf dem Desktop. Einen fixen Balken unter der Browserleiste mit env(safe-area-inset-top) absetzen.",
  "reduzierte_bewegung": "Zwei Haltungen sind vertretbar. Das Chrome-Beispiel blendet den Balken nur bei no-preference ein. Er darf aber auch bleiben, denn er folgt direkt der eigenen Scrollbewegung und bewegt sich nicht von selbst. Weiches Scrollen beim Nach-oben-Knopf dann abschalten.",
  "barrierefreiheit": "Ein reiner Fortschrittsbalken ist dekorativ und bekommt aria-hidden='true'. Eine Kapitelnavigation steht in einem nav mit aria-label und markiert das aktive Kapitel mit aria-current. Der Nach-oben-Knopf ist ein button mit aria-label."
 },
 "messwerte": {
  "easing": "linear (scroll-gekoppelt)",
  "dauer_ms": "auto (scroll-gekoppelt)",
  "stagger_ms": "",
  "distanz": "Höhe 2–4 px typisch (Chrome-Beispiel 1em)",
  "sonstiges": "Balken 2–4px",
  "herkunft": "beobachtet",
  "quelle": "https://developer.chrome.com/docs/modern-web-guidance/guides/ui-atoms/scroll-progress-indicator",
  "aus_eintrag": [
   "scroll-fortschritt",
   "fortschritt-kapitelanzeige"
  ]
 },
 "kurve": {
  "bezier": [
   0,
   0,
   1,
   1
  ],
  "css": "cubic-bezier(0, 0, 1, 1)",
  "name": "linear",
  "dauer_ms": null
 },
 "gesehen_bei": [
  {
   "seite": "Chrome Developers: Scroll progress indicator",
   "url": "https://developer.chrome.com/docs/modern-web-guidance/guides/ui-atoms/scroll-progress-indicator",
   "auszeichnung": "",
   "beobachtung": "animation: grow-progress auto linear; animation-timeline: scroll() (nach dem Shorthand deklarieren), transform-origin 0 50%, gated in no-preference + @supports, aria-hidden, Polyfill nicht empfohlen.",
   "art": "artikel"
  },
  {
   "seite": "scroll-driven-animations.style – Reading Progress Indicator",
   "url": "https://scroll-driven-animations.style/demos/progress-bar/css/",
   "auszeichnung": "",
   "beobachtung": "Reiner CSS-Lesebalken über scroll()-Timeline.",
   "art": "demo"
  },
  {
   "seite": "OFF+BRAND",
   "url": "https://www.itsoffbrand.com",
   "auszeichnung": "",
   "beobachtung": "Prozentfolge 5 %–100 % im Hero-Markup (Lade-/Fortschrittszähler als Typo-Element).",
   "art": "website",
   "browser_gemessen": true
  },
  {
   "seite": "Chrome 154 – scroll-marker-group links/tabs-Modi",
   "url": "https://developer.chrome.com/blog/new-in-chrome-154?hl=en",
   "auszeichnung": "",
   "beobachtung": "Native Scroll-Marker bekommen Link- oder Tab-Semantik.",
   "art": "artikel"
  }
 ],
 "tutorials": [
  {
   "titel": "Chrome: Scroll progress indicator",
   "url": "https://developer.chrome.com/docs/modern-web-guidance/guides/ui-atoms/scroll-progress-indicator"
  },
  {
   "titel": "Reading Progress Indicator",
   "url": "https://scroll-driven-animations.style/demos/progress-bar/css/"
  },
  {
   "titel": "scroll() Parameter-Tool",
   "url": "https://scroll-driven-animations.style/tools/scroll-timeline/params/"
  }
 ],
 "kombinierbar_mit": [
  "pinned-scrub-scrollytelling",
  "horizontal-scroll-section",
  "bildsequenz-video-scrub",
  "scrollspy-kapitelnavigation"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/mikroanimationen/scroll-fortschritt/",
  "meta": "https://cecodesign.de/lab/fundus/mikroanimationen/scroll-fortschritt/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/mikroanimationen/scroll-fortschritt/demo"
 },
 "herkunft": {
  "quelldateien": [
   "hover.json",
   "scroll.json"
  ],
  "zusammengelegt_aus": [
   "scroll-fortschritt",
   "fortschritt-kapitelanzeige"
  ],
  "querverweis_kategorien": [
   "Scroll & Section-Animationen"
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Magazinartikel des erfundenen Tidehaus Flensburg: Lesebalken unter der Kopfzeile, Ring um den Nach-oben-Knopf oder Fortschritt je Kapitel, alles rein in CSS an den Scroll gekoppelt.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "easing": "linear, 1:1 an den Scroll gekoppelt (keine eigene Dauer)",
   "balken": "position absolute direkt unter der Kopfzeile (top 100 %, 1px-Unterkante darüber), Höhe 4 px, volle Breite, Farbe #2a7043; transform-origin 0 50 %; @keyframes scaleX(0) → scaleX(1); animation: wachsen auto linear both; animation-timeline: scroll(root block) (nach dem Shorthand)",
   "ring": "SVG-Kreis r 32 in 68 × 68 px um einen 56-px-Knopf (inset -6 px), Strich 2,5 px, pathLength 1, stroke-dasharray 1, stroke-dashoffset 1 → 0, Start oben (rotate -90°); Spur rgba(11,11,11,.16); gleiche Zeitleiste scroll(root block); daneben Restlesezeit „Noch n Min.“ = ceil(7 × (1 − Fortschritt)), ab 98,5 % „Gelesen“",
   "kapitel": "4 Segmente à 1fr, Spalt 6 px, Höhe 4 px, Innenabstand wie die Kopfzeile; je Kapitel view-timeline: --k1 … --k4 block, view-timeline-inset: var(--kopf) 0, timeline-scope: --k1, --k2, --k3, --k4 auf body; animation-range: contain 0% contain 100%; Longhands statt Shorthand, damit animation-timeline je Segment nicht zurückgesetzt wird; dieselbe Füllung als 2-px-Linie in der Kapitelliste links",
   "aktiv": "aria-current am Kapitel-Link, sobald die Kapitel-Oberkante 35 % der Viewporthöhe unter der Kopfzeile erreicht (Scroll-Listener mit requestAnimationFrame); auf dem Telefon steht das aktive Kapitel in der Kopfzeile",
   "fallback": "ohne animation-timeline: Scroll-Listener setzt --p (0–1) am Root und --k je Segment, gleiche contain-Logik in JS; CSS nutzt scaleX(var(--p)) bzw. stroke-dashoffset: calc(1 - var(--p))",
   "ui": "Variantenwechsel: opacity bzw. translateY 8 px → 0, 200–250 ms cubic-bezier(0.215, 0.61, 0.355, 1); Hover 150 ms gleiche Kurve",
   "kopf": "sticky, 64 px (Telefon 56 px) + env(safe-area-inset-top), 1 px Unterkante #0b0b0b",
   "springen": "Nach oben und Kapitel-Links: scrollTo behavior smooth, bei reduzierter Bewegung sofort; scroll-margin-top Kopf + 24 px",
   "vorfuehren": "Selbst-Scroll 8200 ms je Runde: 5 % Halt, dann 85 % Kosinus-Gleiten bis ganz unten, Sprung nach oben; Vorschau beginnt mit Kapitel und 1400 ms Vorlauf, wechselt jede Runde die Variante; reduziert: Sprünge auf 0/25/50/75/100 % alle 1400 ms",
   "farben": "#efede9 Grund, #0b0b0b Text und Linien, #5f5d58 leise, #2a7043 Sparte Kunst (Fortschritt, Schlüsselbild)",
   "schriften": "Schibsted Grotesk 860 für h1 clamp(2.75rem, 7vw, 7rem)/1, -0.02em; Kapitel 800 clamp(1.75rem, 1.2rem + 1.6vw, 2.625rem); Atkinson Hyperlegible Next 1.125rem/1.6, max. 68ch; IBM Plex Mono 500 0.8125rem tabular-nums für Daten und Labels"
  },
  "ausloeser": "scroll",
  "touch": "Identisch, weil an den Scroll gekoppelt. Unter 900 px entfällt die Kapitelliste; in der Variante Kapitel zeigt die Kopfzeile das aktive Kapitel. Der Nach-oben-Knopf rückt über die Demo-Leiste, Hover-Zustände sind unter (hover: none) neutralisiert.",
  "reduziert": "Balken, Ring und Segmente bleiben, weil sie sich nur mit der eigenen Scrollbewegung ändern und nie von selbst. Übergänge beim Variantenwechsel und weiches Scrollen entfallen; die Vorführung springt in Vierteln statt zu gleiten.",
  "korrekturen": {
   "beschreibung": "Ein schmaler Balken oben oder ein Ring wächst mit dem Scrollfortschritt. In CSS reicht animation-timeline: scroll() mit scaleX von 0 nach 1 und transform-origin links. Ohne Unterstützung übernimmt ein kleiner Scroll-Listener, bei rein dekorativem Zweck lässt man den Balken weg. Die ausführliche Fassung mit Kapitelanzeige steht unter fortschritt-kapitelanzeige.",
   "warum_es_wirkt": "Leser sehen, wie weit sie in einem langen Artikel oder einer Case Study sind und wie viel noch kommt. Das senkt die Hürde, weiterzulesen. Nebenbei ist der Balken ein präzises grafisches Detail, das den Rahmen der Seite lebendig macht.",
   "wann_einsetzen": "Lange Artikel, Case Studies, Dokumentationen und lange Landingpages. Außerdem gepinnte Scrollytelling-Strecken und horizontale Sections, bei denen man sonst die Orientierung verliert.",
   "wann_nicht": "Auf kurzen Seiten. Wenn eine Scrollspy-Navigation den Fortschritt schon zeigt. Als reine Dekoration ohne Orientierungsnutzen.",
   "varianten": [
    "Lesebalken oben: scaleX über scroll(root)",
    "Ring um den Nach-oben-Knopf: SVG stroke-dashoffset oder conic-gradient mit scroll-timeline",
    "Fortschritt je Abschnitt: view-timeline je Section, mit timeline-scope für den fixen Balken",
    "Kapitelnavigation mit aktivem Zustand: IntersectionObserver oder scroll-state, aria-current",
    "Kleiner Prozentzähler 00–100 als typografisches Element über @property und counter()",
    "Schrittanzeige im Karussell: ::scroll-marker und ::scroll-marker-group",
    "JS-Fortschrittsbalken (z. B. mit Motion), wenn CSS nicht reicht"
   ],
   "umsetzung": "@media (prefers-reduced-motion: no-preference) { @supports (animation-timeline: scroll()) { @keyframes grow { from { transform: scaleX(0) } to { transform: scaleX(1) } } #progress { position: fixed; inset: 0 0 auto 0; block-size: 3px; background: var(--accent); transform-origin: 0 50%; animation: grow auto linear; animation-timeline: scroll() } } } <div id='progress' aria-hidden='true'></div>\n\nanimation-timeline immer nach dem Shorthand animation deklarieren, sonst wird sie zurückgesetzt. Kurzform mit scale: @keyframes grow { from { scale: 0 1 } } und animation-timeline: scroll(root block). Fortschritt je Section: benannte view-timeline auf der Section, timeline-scope auf body, damit der fixe Balken sie referenzieren kann; animation-range: contain 0% contain 100%. Prozentzahl: @property --p { syntax: '<integer>'; inherits: false; initial-value: 0 } animieren und per counter() ausgeben. Einen Polyfill empfiehlt Chrome nicht.",
   "mobil": "Verhält sich wie auf dem Desktop. Einen fixen Balken unter der Browserleiste mit env(safe-area-inset-top) absetzen.",
   "reduzierte_bewegung": "Zwei Haltungen sind vertretbar. Das Chrome-Beispiel blendet den Balken nur bei no-preference ein. Er darf aber auch bleiben, denn er folgt direkt der eigenen Scrollbewegung und bewegt sich nicht von selbst. Weiches Scrollen beim Nach-oben-Knopf dann abschalten.",
   "barrierefreiheit": "Ein reiner Fortschrittsbalken ist dekorativ und bekommt aria-hidden='true'. Eine Kapitelnavigation steht in einem nav mit aria-label und markiert das aktive Kapitel mit aria-current. Der Nach-oben-Knopf ist ein button mit aria-label."
  },
  "geprueft": "01.11.2026",
  "notiz": "Welt: Rezept kultur-programm-haltung, erfundenes Tidehaus Flensburg (Kunst, Musik, Film), Magazinartikel zur Ausstellung „Mittelwasser“ mit Programmliste und Besuchsblock. Das Rezept passt gut: Lesefortschritt und Kapitel bedienen die Signatur scrollspy-kapitelnavigation; einen großen Prozentzähler verbietet das Rezept, daher nur Restlesezeit am Ring. Drei Varianten per Umschalter (Balken, Ring, Kapitel), alle rein in CSS (scroll()/view-timeline), JS nur für aria-current, Restlesezeit und den Fallback. Schlüsselbild ist eine eigene SVG (30 Linien, deterministisch erzeugt). Stolperstein: Shorthand animation setzt animation-timeline zurück, auch bei höherer Spezifität eines anderen Selektors; daher Longhands bei den Kapitel-Segmenten. AD-Review 01.11.2026: Note 4. Ausstellungstitel „Pegelstand“ in „Mittelwasser“ geändert (Titel kam schon in typo-maske-medien vor). Pult am Desktop auf die Breite der Inhaltsspalte begrenzt, damit es beim Lesen keinen Text verdeckt. Zugang 02.11.2026: Sparte Kunst #2f7d4a → #2a7043 (5,1:1 auf Off-White, Ecklabels auf der grünen Tafel jetzt voll #efede9 = 5,1:1); Knopf „Nach oben“ ist außerhalb der Ring-Variante inert; Knopf-Rahmen im Kontrastmodus."
 }
}
