{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "bewegung-als-css-funktion",
 "name": "Bewegung als CSS-Funktion",
 "name_en": "Motion as CSS functions: linear() springs and sibling-index() staggering",
 "kurz": "Die Laden-Partitur einer Boulderhalle als reines CSS: drei gerechnete linear()-Federn als Tokens, H1-Zeilen und Kurskacheln gestaffelt über sibling-index() mit Obergrenze aus sibling-count(), @function als Experiment.",
 "kategorie": "Animationsstile",
 "kategorie_slug": "animationsstile",
 "kategorie_nr": 14,
 "bau_chat": "C6",
 "prioritaet": "F",
 "trendstatus": "aufsteigend",
 "belegstatus": "quellenbelegt",
 "website_belege": 0,
 "stimmung": [
  "präzise",
  "verspielt",
  "experimentell"
 ],
 "stimmung_roh": [
  "verspielt",
  "präzise",
  "experimentell"
 ],
 "technik": [
  "css",
  "steps-easing",
  "@property"
 ],
 "technik_gruppen": [
  "css"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Die Bewegungs-Partitur eines Rezepts wird reines CSS. Federn und Aufprall stehen als linear()-Kurven in tokens.css, gerechnet einmal aus Steifigkeit und Dämpfung. Die Staffelung kommt aus sibling-index() und sibling-count(), mit einer Obergrenze für die Gesamtdauer. Ein @function-Experiment fasst die Staffelregel in eine eigene Funktion, mit festen Variablen als Rückfall. Kein JavaScript bewegt etwas.",
  "warum_es_wirkt": "Federn wirken lebendig, solange sie sparsam und überall gleich sind. Als Token in tokens.css bekommt jede Seite dieselbe Feder, und der Browser rechnet sie auf dem Compositor. Staffelung aus der Position im DOM passt sich von selbst an, wenn der Kunde eine Kachel ergänzt, und die Obergrenze verhindert, dass zwölf Kacheln eine Sekunde warten.",
  "wann_einsetzen": "Beim Übersetzen einer Rezept-Partitur in tokens.css, vor allem bei verspielten Rezepten (Freizeit, Fitness, Kurs, D2C), wo kleine Elemente federn dürfen. Für Listen und Raster, die nacheinander erscheinen. Für Häkchen, Zähler, Abzeichen.",
  "wann_nicht": "Federn nie auf Flächen, Fotos oder Deckkraft. Keine Staffelung für Inhalte, die man sofort lesen muss (Öffnungszeiten, Preise, freie Plätze). @function und if() nicht als einzige Quelle: ohne Chromium gibt es sie nicht.",
  "varianten": [
   "Partitur: Laden-Partitur eines Rezepts als CSS, H1-Zeilen gestaffelt, Zähler und Häkchen federn",
   "Federn: drei linear()-Kurven (weich, federnd, Aufprall) mit Kurvenbild und Wirkung im Vergleich",
   "Staffel: sibling-index() mit Obergrenze per sibling-count(), linear, von der Mitte, gedeckelt"
  ],
  "umsetzung": "1. Federn einmal offline rechnen (gedämpfte Schwingung x(t) = 1 − e^(−ζωt)·(cos(ω_d t) + ζω/ω_d·sin(ω_d t)), 40 bis 60 Stützpunkte) und als --ease-feder: linear(…) in tokens.css schreiben, mit Dauer, bei der die Schwingung unter 0,1 % ist. Aufprall als zweite Kurve aus Parabelbögen. 2. Rückfall für alte Browser: @supports not (transition-timing-function: linear(0, 1)) { --ease-feder: cubic-bezier(0.34, 1.56, 0.64, 1) }. 3. Partitur: Jede Rolle bekommt ihr Token (--dauer-laden-1, --dauer-laden-1-versatz, --ease-ein …). 4. Staffeln: animation-delay: calc(var(--ab) + (sibling-index() - 1) * var(--versatz)). Obergrenze: Versatz = min(var(--versatz), var(--budget) / sibling-count()). Von der Mitte: abs(sibling-index() - (sibling-count() + 1) / 2). 5. Rückfall ohne sibling-index(): @supports not (z-index: sibling-index()) setzt :nth-child(1…12) { --i: 0…11 } aus einer Liste. 6. Experiment: @function --staffel(--i <number>, --n <number>) returns <time> { result: min(var(--versatz), var(--budget) / var(--n)) * var(--i); } nur hinter @supports at-rule(@function) bzw. als zusätzliche Deklaration nach der festen. 7. Reduziert: Tokens im @media (prefers-reduced-motion) auf Überblenden 150 ms und Versatz 0 umstellen.",
  "mobil": "Gleich. Staffelung mit Obergrenze ist auf dem Telefon wichtiger, weil dort mehr Kacheln untereinander stehen und sonst die letzten zu spät kommen.",
  "reduzierte_bewegung": "Tokens schalten um: Federn werden zur Überblendung 150 ms ohne Überschwingen, Versatz 0. Die Kurvenbilder bleiben als Abbildung stehen.",
  "barrierefreiheit": "Nur Bewegung, keine Inhalte hängen davon ab: Alles ist ohne Animation sofort im DOM und lesbar. Keine Bewegung länger als 1 s. Das Kurvenbild hat eine Textbeschreibung (Spitze, Dauer)."
 },
 "messwerte": {
  "easing": "Feder linear() aus Steifigkeit 180, Dämpfung 14, Masse 1 (ζ 0,52, Spitze 1,146); weich aus 140 / 22,4 (ζ 0,95); Aufprall aus Fall plus drei Sprüngen mit Rückprall 0,42; UI cubic-bezier(0.16, 1, 0.3, 1)",
  "dauer_ms": "H1 450 je Zeile (Partitur), Zähler und Häkchen 400, weich 600, Feder 800, Aufprall 900, Kacheln 500",
  "stagger_ms": "40 (H1 laut Partitur ab 0/40/80), Kacheln 50 mit Obergrenze 300 gesamt (min(50ms, 300ms / sibling-count()))",
  "distanz": "H1 aus Maske 100 %, Kacheln 16 px",
  "sonstiges": "Höchstens eine federnde Bewegung zugleich (Rezept-Budget). linear()-Stützpunkte mit Douglas-Peucker auf 21 bis 41 Punkte vereinfacht (Abweichung ≤ 0,25 %).",
  "herkunft": "eigene Festlegung",
  "quelle": "Rezept freizeit-erlebnis-ticket, Partitur Stand 04.11.2026"
 },
 "kurve": {
  "bezier": [
   0.16,
   1.0,
   0.3,
   1.0
  ],
  "css": "cubic-bezier(0.16, 1, 0.3, 1)",
  "name": "expo.out",
  "dauer_ms": 450
 },
 "gesehen_bei": [
  {
   "seite": "caniuse: linear() easing",
   "url": "https://caniuse.com/wf-linear-easing",
   "auszeichnung": "",
   "beobachtung": "Abgerufen 05.11.2026: linear() ab Chrome 113, Firefox 112, Safari 17.2 (auch iOS).",
   "art": "artikel"
  },
  {
   "seite": "web-features explorer: sibling-count() and sibling-index()",
   "url": "https://web-platform-dx.github.io/web-features-explorer/features/sibling-count/",
   "auszeichnung": "",
   "beobachtung": "Abgerufen 05.11.2026: Baseline neu verfügbar seit 18.08.2026: Chrome 138, Safari 26.2, Firefox 154.",
   "art": "artikel"
  },
  {
   "seite": "caniuse: CSS at-rule @function",
   "url": "https://caniuse.com/mdn-css_at-rules_function",
   "auszeichnung": "",
   "beobachtung": "Abgerufen 05.11.2026: @function ab Chrome 139 und Edge 139; Firefox bis 162 nein, Safari nur Technology Preview.",
   "art": "artikel"
  },
  {
   "seite": "web-features explorer: if()",
   "url": "https://web-platform-dx.github.io/web-features-explorer/features/if",
   "auszeichnung": "",
   "beobachtung": "Abgerufen 05.11.2026: if() nur Chrome und Edge ab 137, Firefox und Safari nicht; eingeschränkt verfügbar.",
   "art": "artikel"
  },
  {
   "seite": "Chrome for Developers: linear() easing function",
   "url": "https://developer.chrome.com/docs/css-ui/css-linear-easing-function",
   "auszeichnung": "",
   "beobachtung": "Erklärt Federn und Aufprall als linear() mit Stützpunkten. In dieser Runde nur über die Suche gefunden, nicht abgerufen.",
   "art": "tutorial"
  }
 ],
 "tutorials": [
  {
   "titel": "MDN: linear()",
   "url": "https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function/linear"
  },
  {
   "titel": "MDN: sibling-index()",
   "url": "https://developer.mozilla.org/en-US/docs/Web/CSS/sibling-index"
  },
  {
   "titel": "MDN: @function",
   "url": "https://developer.mozilla.org/en-US/docs/Web/CSS/@function"
  }
 ],
 "kombinierbar_mit": [
  "token-federnd-verspielt",
  "token-toggle-asymmetrisch",
  "gestaffelte-einblendung",
  "split-mask-reveal",
  "checkbox-radio-animiert",
  "icon-squash-stretch",
  "druck-feedback"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/animationsstile/bewegung-als-css-funktion/",
  "meta": "https://cecodesign.de/lab/fundus/animationsstile/bewegung-als-css-funktion/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/animationsstile/bewegung-als-css-funktion/demo"
 },
 "herkunft": {
  "quelldateien": [
   "Recherche Runde 4, 04.11.2026"
  ],
  "pruefnotizen": [
   "Recherche Runde 4 nannte @function und if() mit ungeprüftem Browserstand. Geprüft 05.11.2026: @function nur Chrome und Edge ab 139, if() nur ab 137. Deshalb hier nur Experiment hinter @supports; das Muster trägt sich über linear() (Baseline seit Safari 17.2) und sibling-index() (Baseline neu seit 18.08.2026).",
   "Abgrenzung: token-federnd-verspielt ist ein Bewegungsstil, gestaffelte-einblendung eine einzelne Staffelung nach Filterwechsel. Dieses Muster zeigt, wie eine Rezept-Partitur ohne JS als Tokens umgesetzt wird.",
   "Federwerte eigene Festlegung; Dauern aus der Partitur von freizeit-erlebnis-ticket (Stand 04.11.2026).",
   "Demo 05.11.2026: sibling-index() in einer unregistrierten Custom Property wird erst dort ausgewertet, wo var() sie nutzt. Für die H1-Zeilen (Animation am inneren span) deshalb @property --zi { syntax: '<number>'; inherits: true } an der Zeile."
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Die Laden-Partitur einer Boulderhalle als reines CSS: drei gerechnete linear()-Federn als Tokens, H1-Zeilen und Kurskacheln gestaffelt über sibling-index() mit Obergrenze aus sibling-count(), @function als Experiment.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "ease_weich": "linear() aus k 140, c 22,4, m 1 (ζ 0,95), 600 ms, 21 Stützpunkte",
   "ease_feder": "linear() aus k 180, c 14, m 1 (ζ 0,52), Spitze 1,146 bei 35 %, 800 ms, 27 Stützpunkte",
   "ease_aufprall": "linear() aus Parabel-Fall + 3 Sprüngen, Rückprall 0,42 (tiefster Punkt 0,824), 900 ms, 41 Stützpunkte",
   "rueckfall_linear": "@supports not (transition-timing-function: linear(0, 1)): Feder und Aufprall cubic-bezier(0.34, 1.56, 0.64, 1), weich cubic-bezier(0.16, 1, 0.3, 1)",
   "partitur_h1": "--dauer-laden-1 450 ms, --ui-ease-ein cubic-bezier(0.16, 1, 0.3, 1), Verzug calc(--dauer-laden-1-ab + --zi × --dauer-laden-1-versatz 40 ms); --zi per @property <number> = sibling-index() − 1 an der Zeile",
   "zaehler_haken": "--dauer-zaehler 400 ms --ease-feder; Zähler scale .6 → 1, Häkchen scale 0 → 1 (aus 120 ms --ui-ease-aus)",
   "staffel": "Versatz 50 ms, Budget 300 ms, Dauer 500 ms, translateY 16 px; gedeckelt min(50ms, 300ms / sibling-count()) × (sibling-index() − 1); Mitte max(i − (n+1)/2, (n+1)/2 − i) × 50 ms",
   "funktion": "@function --staffel(--i <number>, --n <number>) returns <time> als zweite animation-delay-Deklaration; ohne Unterstützung verworfen",
   "rueckfall_index": "@supports not (z-index: sibling-index()): :nth-child(1…24) setzt --i, :has(> li:nth-child(n):last-child) setzt --n",
   "erkennung": "CSS.supports('z-index', 'sibling-index()'); @function per Probe-Element (transition-duration --probe() = 7ms)",
   "reduziert": "Tokens: alle Kurven linear, Dauern 150 ms, Versatz 0 (Media Query und .reduziert)",
   "schrift": "Anybody wdth 70 wght 850 h1 clamp(2.75rem, 1.2rem + 6.4vw, 6.5rem) Versal, TikTok Sans 17 px, Geist Mono Labels",
   "farben": "#F4F3EF Hallengrau, #17161A Text, #E6E3DA Matte, #19181D Halle, #AE1650 Griff-Magenta, #F5B8CE Magenta hell auf Dunkel"
  },
  "ausloeser": "laden",
  "touch": "Gleich; Kurvenkarten stehen untereinander (Kurve, Wirkung, Werte), Partitur-Spuren mit schmaler Beschriftung, Kacheln zweispaltig.",
  "reduziert": "Tokens schalten um: Überblenden 150 ms ohne Überschwingen, kein Versatz; Kurvenbilder bleiben als Abbildung, der Punkt springt ans Ende.",
  "korrekturen": {},
  "geprueft": "05.11.2026",
  "notiz": "Welt: Rezept freizeit-erlebnis-ticket, erfundene Boulderhalle Griffwerk in Wolfsburg. Anybody und TikTok Sans, Hallengrau und Griff-Magenta. Partitur aus rezept.bewegung (Stand 04.11.2026): H1 ab 0/40/80 ms je 450 ms, Zeitfenster stehen, Zähler und Häkchen federn. Kurven offline mit Python gerechnet (gedämpfte Schwingung, Douglas-Peucker). Browserstand 05.11.2026: linear() Chrome 113, Firefox 112, Safari 17.2; sibling-index() Baseline seit 18.08.2026; @function nur Chrome/Edge ab 139, if() ab 137 (deshalb nur Experiment). Vorführung: Laden abspielen, Zähler und Häkchen; Federn im Takt; Staffel wechselt gedeckelt, linear, Mitte. Selbsturteil 4.",
  "varianten": [
   {
    "id": "partitur",
    "name": "Partitur als CSS",
    "wann": "Beim Übersetzen einer Rezept-Partitur in tokens.css: Hero mit gestaffelten H1-Zeilen, kleine Elemente federn, Rest steht.",
    "werte": {
     "zeigt": "Hero + Partitur-Spuren aus denselben Tokens",
     "staffel": "sibling-index() × 40 ms"
    }
   },
   {
    "id": "federn",
    "name": "Drei Federn",
    "wann": "Wenn ein verspieltes Rezept Federn braucht: Kurven als Token wählen (weich für Flächen, Feder für Zähler, Aufprall sparsam).",
    "werte": {
     "zeigt": "Kurvenbild aus dem Token, Punkt läuft X linear / Y mit Kurve, Wirkung daneben"
    }
   },
   {
    "id": "staffel",
    "name": "Staffel mit Obergrenze",
    "wann": "Raster und Listen, die nacheinander erscheinen (Kurse, Zeitfenster, Projekte), deren Anzahl der Kunde ändert.",
    "werte": {
     "zeigt": "4 bis 24 Kacheln, linear / Mitte / gedeckelt",
     "budget": "300 ms gesamt"
    }
   }
  ]
 }
}
