{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "skeleton-shimmer",
 "name": "Skeleton mit Schimmer",
 "name_en": "Skeleton loading with shimmer",
 "kurz": "Graue Platzhalter in exakter Größe, über die eine Lichtkante wandert; die Inhalte blenden ohne Layoutsprung herein.",
 "kategorie": "Mikroanimationen",
 "kategorie_slug": "mikroanimationen",
 "kategorie_nr": 9,
 "bau_chat": "C4",
 "prioritaet": "A",
 "trendstatus": "etabliert",
 "belegstatus": "belegt",
 "website_belege": 4,
 "stimmung": [
  "ruhig",
  "präzise"
 ],
 "stimmung_roh": [
  "ruhig",
  "funktional",
  "modern"
 ],
 "technik": [
  "css"
 ],
 "technik_gruppen": [
  "css"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Statt eines Spinners zeigt der Platz die künftige Struktur als graue Formen: Bildflächen, Textzeilen, Avatare, jeweils in exakter Größe. Eine helle Lichtkante wandert darüber (Schimmer), oder die Formen pulsieren in der Deckkraft. Sobald die Daten da sind, blendet der echte Inhalt in 200 bis 300 ms über. Das Layout bleibt stehen.",
  "warum_es_wirkt": "Die Seite zeigt sofort, was kommt. Das Auge kann sich schon orientieren, die Wartezeit wirkt kürzer. Weil Platzhalter und Inhalt gleich groß sind, gibt es keinen Layoutsprung (CLS). Der Inhalt wächst in seine Form hinein.",
  "wann_einsetzen": "Listen, Karten, Dashboards, Bildergalerien, nachgeladene Abschnitte und KI-Antworten. Überall, wo die Struktur vorher feststeht und das Laden spürbar dauert.",
  "wann_nicht": "Bei sehr kurzen Ladezeiten unter etwa 300 ms: dann gar nichts zeigen, sonst flackert es. Bei unbekannter Struktur: dann lieber Spinner oder Fortschrittsanzeige.",
  "varianten": [
   "Schimmer: Lichtkante per background-position-Animation, einzeln über jede Form.",
   "Synchron: dieselbe Animation mit background-attachment: fixed. Eine gemeinsame Lichtwelle läuft über alle Formen.",
   "Pulsieren: nur die Deckkraft schwingt, ruhiger und ohne Richtung.",
   "Bild-Platzhalter: Mittelfarbe oder 20 bis 30 px breite Mini-Vorschau (unscharf) in festem Seitenverhältnis, das Bild blendet nach decode() in etwa 150 ms ein; nie beim LCP-Bild. ThumbHash statt BlurHash bei transparenten Bildern"
  ],
  "umsetzung": "Gerüst und Inhalt liegen in derselben Grid-Zelle (grid-area: 1 / 1). So bestimmt der Inhalt die Größe, und beim Wechsel springt nichts. Schimmer: .sk { background: #dad2c3 linear-gradient(100deg, transparent 62%, var(--licht) 75%, transparent 88%) 0 0 / 200% 100% repeat-x; animation: schimmer 1.5s cubic-bezier(.42,0,.58,1) infinite } @keyframes schimmer { to { background-position: -200% 0 } }. Synchron: zusätzlich background-attachment: fixed. Pulsieren: @keyframes puls { 50% { opacity: .5 } } bei Grundwert .8, 2 s. Bildflächen mit aspect-ratio, Zeilen 0,74em hoch mit der Schriftgröße des echten Textes. Ankunft: Gerüst und Inhalt tauschen die Deckkraft in 250 ms. Liste mit aria-busy=\"true\", Gerüst aria-hidden.",
  "mobil": "Identisch. Auf schmalen Schirmen passt sich das Gerüst dem mobilen Raster an (z. B. Liste mit Daumenbild). Hinweis: iOS Safari ignoriert background-attachment: fixed, dort läuft die synchrone Variante wie der einfache Schimmer.",
  "reduzierte_bewegung": "Kein wandernder Verlauf. Entweder statisches Grau (so macht es 14islands) oder ein sehr langsames Pulsieren. Chrome empfiehlt für Ladezustände: verlangsamen statt stoppen, etwa 6 s statt 1,5 s.",
  "barrierefreiheit": "aria-busy=\"true\" am Container, solange geladen wird, danach false. Das Gerüst ist aria-hidden. Den Abschluss bei Bedarf über eine aria-live-Region melden, z. B. „Drei Beiträge geladen“. Der Kontrast der Platzhalter muss nicht hoch sein, sie tragen keine Information."
 },
 "messwerte": {
  "easing": "ease-in-out",
  "dauer_ms": "1500 (Quai) / 8000 (14islands) pro Durchlauf",
  "stagger_ms": "",
  "distanz": "background-size 200–400 %, Positionswechsel 200 % → −200 %",
  "sonstiges": "Reduced-Motion-Fallback statisch (14islands)",
  "herkunft": "beobachtet",
  "quelle": "https://www.qu.ai/ ; https://14islands.com/_next/static/css/b40ae3ae3dc88ad5.css"
 },
 "kurve": {
  "bezier": [
   0.42,
   0.0,
   0.58,
   1.0
  ],
  "css": "cubic-bezier(0.42, 0, 0.58, 1)",
  "name": "ease-in-out",
  "dauer_ms": 1500
 },
 "gesehen_bei": [
  {
   "seite": "Motion Examples: Skeleton Shimmer",
   "url": "https://motion.dev/examples/react-skeleton-shimmer",
   "auszeichnung": "",
   "beobachtung": "Offizielles Beispiel (in Übersicht gelistet).",
   "art": "demo"
  },
  {
   "seite": "Chrome Developers: Spinner",
   "url": "https://developer.chrome.com/docs/modern-web-guidance/guides/ui-components/spinner",
   "auszeichnung": "",
   "beobachtung": "Reduced-Motion-Prinzip für Ladezustände: verlangsamen statt stoppen (6 s statt 1.5 s), damit Aktivität sichtbar bleibt.",
   "art": "artikel"
  },
  {
   "seite": "Quai Network",
   "url": "https://www.qu.ai/",
   "auszeichnung": "",
   "beobachtung": ".skeleton: linear-gradient(90deg, weiß 4 % / 8 % / 4 %), background-size 200 % 100 %, animation shimmer 1.5s ease-in-out infinite (→ background-position −200 %).",
   "art": "website"
  },
  {
   "seite": "14islands",
   "url": "https://14islands.com/",
   "auszeichnung": "",
   "beobachtung": "Tweet-Skeleton: background-size 400 % 100 %, animation 8s ease-in-out infinite, bei prefers-reduced-motion: animation none.",
   "art": "website"
  },
  {
   "seite": "Bolt",
   "url": "https://bolt.new/",
   "auszeichnung": "",
   "beobachtung": "Design-System-Skeleton: .bolt-ds-skeleton-shimmer nur unter @media (prefers-reduced-motion: no-preference) sichtbar, 1.5s ease-in-out infinite translate(-100%) → translate(100%); Pulse-Variante opacity .8 ↔ .5 (assets/src-DCRnbyxm.css).",
   "art": "website"
  },
  {
   "seite": "v0 by Vercel",
   "url": "https://v0.app/",
   "auszeichnung": "",
   "beobachtung": "Overlay über generierten Bereichen: 2s ease-in-out infinite Pulse (#80808026 ↔ #80808014, dunkel #00000059 ↔ #00000061) plus Lichtstreifen linear-gradient(105deg, transparent 40 %, #ffffff05 45 %, #ffffff0a 50 %, #ffffff05 55 %, transparent 60 %) mit translate -100% → 100% (chat-static/…/2k9vu604j0f3b.css).",
   "art": "website"
  }
 ],
 "tutorials": [
  {
   "titel": "Motion: Skeleton Shimmer",
   "url": "https://motion.dev/examples/react-skeleton-shimmer"
  }
 ],
 "kombinierbar_mit": [
  "spinner-ladeindikator",
  "gestaffelte-einblendung"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/mikroanimationen/skeleton-shimmer/",
  "meta": "https://cecodesign.de/lab/fundus/mikroanimationen/skeleton-shimmer/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/mikroanimationen/skeleton-shimmer/demo"
 },
 "herkunft": {
  "quelldateien": [
   "hover.json",
   "patch-belege-1.json",
   "patch-luecken-b.json"
  ],
  "pruefnotizen": [
   "patch-belege-1.json: 2 Produktionsbelege.",
   "patch-luecken-b.json: Zwei Produktionsbelege mit beobachteten Werten; Bolt zeigt Best Practice ‚Shimmer nur bei no-preference‘."
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Graue Platzhalter in exakter Größe, über die eine Lichtkante wandert; die Inhalte blenden ohne Layoutsprung herein.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "easing": "cubic-bezier(0.42, 0, 0.58, 1) (ease-in-out, gemessen)",
   "schimmer_dauer_ms": 1500,
   "schimmer_verlauf": "linear-gradient(100deg, transparent 62%, var(--licht) 75%, transparent 88%)",
   "schimmer_background_size": "200% 100%, repeat-x",
   "schimmer_position": "0 0 → -200% 0, infinite",
   "synchron": "wie Schimmer, zusätzlich background-attachment: fixed",
   "puls_dauer_ms": 2000,
   "puls_deckkraft": "0.8 ↔ 0.5 (Keyframes 0/100 % .8, 50 % .5)",
   "farbe_platzhalter": "#e4dfd7 (Sand) auf Grund #f6f6f4",
   "farbe_licht": "color-mix(in oklab, #e4dfd7, white 62%)",
   "radius": "Zeilen 0.4em, Bildflächen 2px",
   "zeilenhoehe_platzhalter": "0.74em der jeweiligen Schriftgröße (Fließtext 0.62em), mittig in der Textzeile: Rand (Zeilenhöhe − Platzhalterhöhe) / 2",
   "ueberblenden_ms": 250,
   "ueberblenden_easing": "cubic-bezier(0.42, 0, 0.58, 1)",
   "ankunft_ms": [
    1800,
    2300,
    2800
   ],
   "reduziert": "kein Verlauf, Puls 6000 ms (0.8 ↔ 0.5)",
   "vorfuehrung": "Laden, 2400 ms Inhalt stehen lassen, nächste Variante (Synchron → Pulsieren → Schimmer)"
  },
  "ausloeser": "laden",
  "touch": "Identisch zum Desktop. Unter 640 px wird die Objektliste zur Liste mit 96-px-Daumenbild; das Gerüst folgt demselben Raster. Größere Tippflächen für Umschalter und „Neu laden“.",
  "reduziert": "Kein wandernder Verlauf. Die Platzhalter pulsieren sehr langsam (6000 ms), damit Aktivität sichtbar bleibt. Das Überblenden zum Inhalt (250 ms Deckkraft) bleibt.",
  "korrekturen": {
   "beschreibung": "Statt eines Spinners zeigt der Platz die künftige Struktur als graue Formen: Bildflächen, Textzeilen, Avatare, jeweils in exakter Größe. Eine helle Lichtkante wandert darüber (Schimmer), oder die Formen pulsieren in der Deckkraft. Sobald die Daten da sind, blendet der echte Inhalt in 200 bis 300 ms über. Das Layout bleibt stehen.",
   "warum_es_wirkt": "Die Seite zeigt sofort, was kommt. Das Auge kann sich schon orientieren, die Wartezeit wirkt kürzer. Weil Platzhalter und Inhalt gleich groß sind, gibt es keinen Layoutsprung (CLS). Der Inhalt wächst in seine Form hinein.",
   "wann_einsetzen": "Listen, Karten, Dashboards, Bildergalerien, nachgeladene Abschnitte und KI-Antworten. Überall, wo die Struktur vorher feststeht und das Laden spürbar dauert.",
   "wann_nicht": "Bei sehr kurzen Ladezeiten unter etwa 300 ms: dann gar nichts zeigen, sonst flackert es. Bei unbekannter Struktur: dann lieber Spinner oder Fortschrittsanzeige.",
   "varianten": [
    "Schimmer: Lichtkante per background-position-Animation, einzeln über jede Form.",
    "Synchron: dieselbe Animation mit background-attachment: fixed. Eine gemeinsame Lichtwelle läuft über alle Formen.",
    "Pulsieren: nur die Deckkraft schwingt, ruhiger und ohne Richtung.",
    "Bild-Platzhalter: Mittelfarbe oder 20 bis 30 px breite Mini-Vorschau (unscharf) in festem Seitenverhältnis, das Bild blendet nach decode() in etwa 150 ms ein; nie beim LCP-Bild. ThumbHash statt BlurHash bei transparenten Bildern"
   ],
   "umsetzung": "Gerüst und Inhalt liegen in derselben Grid-Zelle (grid-area: 1 / 1). So bestimmt der Inhalt die Größe, und beim Wechsel springt nichts. Schimmer: .sk { background: #dad2c3 linear-gradient(100deg, transparent 62%, var(--licht) 75%, transparent 88%) 0 0 / 200% 100% repeat-x; animation: schimmer 1.5s cubic-bezier(.42,0,.58,1) infinite } @keyframes schimmer { to { background-position: -200% 0 } }. Synchron: zusätzlich background-attachment: fixed. Pulsieren: @keyframes puls { 50% { opacity: .5 } } bei Grundwert .8, 2 s. Bildflächen mit aspect-ratio, Zeilen 0,74em hoch mit der Schriftgröße des echten Textes. Ankunft: Gerüst und Inhalt tauschen die Deckkraft in 250 ms. Liste mit aria-busy=\"true\", Gerüst aria-hidden.",
   "mobil": "Identisch. Auf schmalen Schirmen passt sich das Gerüst dem mobilen Raster an (z. B. Liste mit Daumenbild). Hinweis: iOS Safari ignoriert background-attachment: fixed, dort läuft die synchrone Variante wie der einfache Schimmer.",
   "reduzierte_bewegung": "Kein wandernder Verlauf. Entweder statisches Grau (so macht es 14islands) oder ein sehr langsames Pulsieren. Chrome empfiehlt für Ladezustände: verlangsamen statt stoppen, etwa 6 s statt 1,5 s.",
   "barrierefreiheit": "aria-busy=\"true\" am Container, solange geladen wird, danach false. Das Gerüst ist aria-hidden. Den Abschluss bei Bedarf über eine aria-live-Region melden, z. B. „Drei Beiträge geladen“. Der Kontrast der Platzhalter muss nicht hoch sein, sie tragen keine Information."
  },
  "geprueft": "03.11.2026",
  "notiz": "Objektliste der erfundenen Maklerfirma „Weidner Immobilien, Hamburg-Eppendorf“ nach dem Rezept immobilien-diskret-hochwertig (Libre Caslon Display für die Headline, Hanken Grotesk mit Tabellenziffern für Fakten, Grund #f6f6f4, Markenton #02385c, Orange #ed7f1a nur für den CTA „Immobilie bewerten“). Drei Objekte (Altbauwohnung, Penthouse, Stadtvilla) mit eigenen SVG-Bildern (Fassadenansicht, Grundriss, Villa im Garten) laden nach (1,8 / 2,3 / 2,8 s) und blenden einzeln vom Gerüst zum Inhalt über. Umschalter Schimmer, Synchron (background-attachment: fixed, eine Welle über alle Karten) und Pulsieren; „Neu laden“ startet den Ladevorgang neu. Gerüst und Inhalt teilen sich eine Grid-Zelle; Titel und Text sind auf zwei Zeilen begrenzt, die Platzhalterzeilen sitzen auf den Textzeilen (1440, 960 und 390 px gemessen). Status mit aria-live, Liste mit aria-busy. Reines CSS plus wenig JS für die simulierte Ankunft. Bewegungswerte unverändert. Zugang 02.11.2026: --leise Alpha .6 → .72 (5,2:1); CTA-Text #fff → var(--text) #313131 auf Orange (4,7:1); Kurzbeschreibungen auf zwei Zeilen gekürzt, Zeilenbegrenzung nur noch in der Vorschau (bei Textabständen 1.4.12 nichts mehr abgeschnitten); unter 380 px Raster minmax(0, 1fr), Daumenbild 80 px, CTA bricht um (kein Querscrollen bei 320 px); Kontrastmodus-Rahmen für Knöpfe. Varianten 03.11.2026: Umschalter um „Bild-Platzhalter“ ergänzt (?v=basis|bild-platzhalter); Schimmer, Synchron und Puls bleiben die Grundvariante basis. „Bild-Platzhalter“ spielt im Rezept fotograf-film-bild-zuerst (Ines Morawe, Leipzig) mit sechs eigenen Medienbildern (…-hoch.jpg) und dem Hero huegel-nebel.jpg als LCP-Bild ohne Platzhalter. Quellen: responsive-image.dev/usage/lqip (Größenvergleich), jmperezperez.com (Medium, Mini-JPEG etwa 27 px), chromium.googlesource.com/chromium/src/+/main/docs/speed/metrics_changelog/2023_04_lcp.md (0,05 bit/px). Selbsturteil 4.",
  "varianten": [
   {
    "id": "basis",
    "name": "Objektliste mit Schimmer, Synchron und Puls",
    "wann": "Listen, Karten und Dashboards mit bekannter Struktur: Gerüst aus Zeilen und Bildflächen in exakter Größe, umschaltbar zwischen Schimmer, synchroner Lichtwelle und Pulsieren.",
    "werte": {
     "aufbau": "Gerüst und Inhalt in derselben Grid-Zelle",
     "animation": "Schimmer 1500 ms, Puls 2000 ms, ease-in-out",
     "rezept": "immobilien-diskret-hochwertig (Weidner Immobilien, Hamburg)",
     "details": "siehe bau.werte"
    }
   },
   {
    "id": "bild-platzhalter",
    "name": "Bild-Platzhalter aus Farbe oder Mini-Vorschau",
    "wann": "Nachgeladene Bilder in Galerien, Shops und Exposés (Fotografie, Immobilien, Hotel). Nie beim LCP-Bild: dort fetchpriority=\"high\" ohne Platzhalter und ohne Einblenden.",
    "werte": {
     "rahmen": "aspect-ratio 4 / 5, overflow hidden, img absolut mit object-fit cover und width/height-Attributen",
     "mittelfarbe": "background-color je Bild (Mittelwert, hier #ac9c8b, #a7a179, #be764f, #b7967b, #7b7362, #455fb8)",
     "mini_vorschau": "24 × 30 px JPEG (Qualität 42) als Daten-URI, 403 bis 476 Byte, als ::before mit background-size cover, filter blur(14px), inset −8 %",
     "einblenden": "img.decode(), dann opacity 0 → 1 in 150 ms cubic-bezier(0.16, 1, 0.3, 1) (eigene Festlegung); reduziert ohne Übergang",
     "lcp": "Hero huegel-nebel.jpg mit fetchpriority=\"high\", Höhe clamp(180px, 30vh, 420px) aus CSS, kein Platzhalter, kein Einblenden; Chrome zählt Bilder unter 0,05 bit/px nicht als LCP (Chromium metrics_changelog 2023_04_lcp.md), ein Platzhalter verbessert den LCP also nicht",
     "ladezeit": "simuliert 700 bis 2700 ms je Bild (src wird verzögert gesetzt)",
     "pult": "Mini-Vorschau, Mittelfarbe oder Grau #e6e6e6 zum Vergleich",
     "schrift": "Instrument Serif (Name 1.5rem, Titel clamp(1.5rem, 3vw, 2.75rem)), Instrument Sans .875rem, Fragment Mono .75rem für Bildunterschriften",
     "farben": "Grund #f4f4f2, Text #141414, Meta #6d6d6d, Platzhalter-Grau #e6e6e6",
     "vorfuehrung": "laden, 2,4 s stehen lassen, Platzhalter wechselt Mini-Vorschau ↔ Mittelfarbe, neu laden",
     "rezept": "fotograf-film-bild-zuerst (Ines Morawe, Fotografie, Leipzig)"
    }
   }
  ]
 }
}
