{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "intro-ohne-wartezeit",
 "name": "Intro ohne Wartezeit (LCP-sicheres Eröffnungsballett)",
 "name_en": "Non-blocking intro / instant hero reveal",
 "kurz": "Der Hero steht ab dem ersten Frame, Zeilen steigen aus Masken und die Navigation taucht nach: ein inszenierter Auftritt in 1,2 Sekunden, ganz ohne Ladebildschirm.",
 "kategorie": "Preloader & Intro",
 "kategorie_slug": "preloader-intro",
 "kategorie_nr": 2,
 "bau_chat": "C3",
 "prioritaet": "A",
 "trendstatus": "aufsteigend",
 "belegstatus": "teilbelegt",
 "website_belege": 1,
 "stimmung": [
  "ruhig",
  "editorial",
  "luxuriös"
 ],
 "stimmung_roh": [
  "ruhig",
  "souverän",
  "editorial"
 ],
 "technik": [
  "css",
  "clip-path",
  "scroll-driven-css",
  "vanilla-js"
 ],
 "technik_gruppen": [
  "css",
  "js"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Kein blockierender Ladebildschirm: Das HTML liefert die Hero-Inhalte sofort sichtbar aus. Die Eröffnungsanimation läuft per CSS-@keyframes ab dem ersten Rendern, nicht erst nach JavaScript oder window.load. Headline-Zeilen steigen aus Masken, das Hero-Bild öffnet sich auf Wunsch per clip-path, die Navigation taucht nach. Das LCP-Element (Hero-Bild oder H1) wird nie mit opacity: 0 oder display: none versteckt. Es bewegt sich höchstens per Transform oder Clip, oder es steht von Anfang an und nur Nebenelemente animieren. Bilder, die später gebraucht werden, laden während des Intros im Hintergrund.",
  "warum_es_wirkt": "Die Seite wirkt inszeniert, aber niemand wartet. Der Inhalt ist sofort lesbar, die Bewegung ist Zugabe und kein Vorhang. Weil das LCP-Element sichtbar bleibt, misst der Browser einen frühen Largest Contentful Paint. Laut Shopify verbesserte das Entfernen von Fade-ins am LCP-Element den LCP in einzelnen Fällen um 3 bis 6 Sekunden.",
  "wann_einsetzen": "Als Standard für jede Seite, die ein Intro möchte. Besonders bei Seiten, die über Suchmaschinen gefunden werden oder verkaufen sollen: Portfolio, Shop, Agentur, Produktseite.",
  "wann_nicht": "Wenn vor der ersten Interaktion wirklich schwere Assets nötig sind, etwa eine 3D-Szene oder ein Video. Dann besser eine Ladeszene mit echtem Fortschritt (webgl-ladeszene-fortschritt).",
  "varianten": [
   "Reines CSS-Keyframe-Intro, das mit dem ersten Paint startet",
   "LCP-Element steht sofort, nur Nebenelemente animieren",
   "Clip-Path-Reveal statt Opacity-Fade für das Hero-Bild, ab dem ersten Frame minimal sichtbar",
   "Start aus pagereveal: Inhalte nur in Browsern verstecken, die das Event unterstützen"
  ],
  "umsetzung": "Zeilen: .maske > span { display: block; animation: steigen .9s cubic-bezier(.22, 1, .36, 1) both; animation-delay: calc(var(--i) * 80ms) } mit @keyframes steigen { from { transform: translateY(110%) } }. Die Masken-Wrapper (overflow: hidden) stehen im HTML statt per JS-Split, so läuft alles ohne JavaScript. Bild-Reveal: @keyframes oeffnen { from { clip-path: inset(0 0 98% 0) } } mit 1,1 s cubic-bezier(.76, 0, .24, 1). Das Bild ist so ab dem ersten Frame minimal sichtbar. Wie Chrome Clip-Animationen für den LCP bewertet, ist nicht dokumentiert. Deshalb mit Lighthouse oder dem Performance-Panel der DevTools gegenprüfen. Das LCP-Bild bekommt fetchpriority=\"high\" und kein loading=\"lazy\". Fallstrick Webfonts: font-display: swap mit einer Ersatzschrift, deren Metrik per size-adjust und ascent-override angeglichen ist, sonst springt die Headline.",
  "mobil": "Gleicher Ablauf, nur kürzer: Gesamtdauer etwa 800 ms.",
  "reduzierte_bewegung": "Die Animation entfällt, alles steht sofort. Guter Diagnosetest nach Shopify: LCP mit und ohne reduzierte Bewegung vergleichen. Ist der Wert ohne Animation deutlich besser, bremst das Intro.",
  "barrierefreiheit": "Alle Inhalte stehen sofort im DOM und sind lesbar. Kein Overlay, kein Fokus-Trap. Die Masken-Wrapper ändern die Lesereihenfolge nicht."
 },
 "messwerte": {
  "easing": "cubic-bezier(0.22,1,0.36,1) für Text; cubic-bezier(0.76,0,0.24,1) für Clip",
  "dauer_ms": "Shopify-Empfehlung unter 300 für das LCP-Element; Gesamt-Intro typisch 900–1600",
  "stagger_ms": "60–100 je Zeile (typisch)",
  "distanz": "translateY 100–110% innerhalb der Maske",
  "sonstiges": "Mehr als 500 ms zwischen Bild-Download-Ende und LCP-Marker deutet auf Render-Verzögerung durch Animation (Shopify)",
  "herkunft": "beobachtet",
  "quelle": "https://shopify.dev/docs/storefronts/themes/best-practices/performance/dont-hide-lcp-image-behind-animations"
 },
 "kurve": {
  "bezier": [
   0.22,
   1.0,
   0.36,
   1.0
  ],
  "css": "cubic-bezier(0.22, 1, 0.36, 1)",
  "name": "power4.out",
  "dauer_ms": 300
 },
 "gesehen_bei": [
  {
   "seite": "Shopify Theme Best Practices: Don't hide LCP image behind animations",
   "url": "https://shopify.dev/docs/storefronts/themes/best-practices/performance/dont-hide-lcp-image-behind-animations",
   "auszeichnung": "",
   "beobachtung": "Chrome schließt Elemente mit opacity:0 von der LCP-Kandidatur aus. Empfohlen: CSS-@keyframes statt Script-Start, Dauer unter 0,3 s, Seitenübergänge aus pagereveal starten und Inhalte nur dort verstecken, wo das Event unterstützt wird.",
   "art": "artikel"
  },
  {
   "seite": "Thibault Guignand Portfolio",
   "url": "https://www.thibaultguignand.com/",
   "auszeichnung": "",
   "beobachtung": "Nach etwa zehn Perf-Commits: Fonts sofort, Hero-Bild bei Hover, erstes Projekt während des Intros, Rest später. Alles vorzuladen blockierte das erste Rendern, nichts vorzuladen erzeugte Flashes.",
   "art": "website",
   "browser_gemessen": true
  }
 ],
 "tutorials": [
  {
   "titel": "Don't hide LCP image behind animations (Shopify)",
   "url": "https://shopify.dev/docs/storefronts/themes/best-practices/performance/dont-hide-lcp-image-behind-animations"
  },
  {
   "titel": "From Shader Uniforms to Clip-Path Wipes (Preload-Strategie)",
   "url": "https://tympanus.net/codrops/2026/05/06/from-shader-uniforms-to-clip-path-wipes-how-gsap-drives-my-portfolio/"
  }
 ],
 "kombinierbar_mit": [
  "split-mask-reveal",
  "einmal-intro-session",
  "vt-cross-document-mpa"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/preloader-intro/intro-ohne-wartezeit/",
  "meta": "https://cecodesign.de/lab/fundus/preloader-intro/intro-ohne-wartezeit/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/preloader-intro/intro-ohne-wartezeit/demo"
 },
 "herkunft": {
  "quelldateien": [
   "uebergaenge.json",
   "patch-belege-3.json",
   "r3-belege-a.json"
  ],
  "pruefnotizen": [
   "patch-belege-3.json: Kein zweiter live geprüfter Beleg gefunden (Ziel 2 nicht erreicht); Thibault Guignand bleibt einziger Produktionsbeleg. Prio A belassen, weil Muster aus Performance-Sicht empfohlen ist.",
   "r3-belege-a.json (Runde 3, 31.10.2026): Kein belastbarer zusätzlicher Produktionsbeleg. Hero-Keyframes bei Resend (hero-scale-in 1s ease-out .1s both, scale .97 → 1, opacity bis 30 % auf 0), Vercel (fade-in, --hero-duration 350ms, cubic-bezier(.455,.03,.515,.955)) und Attio (ask-hero-rise .9s cubic-bezier(.23,1,.32,1), blur 6px, translateY 16px) stehen in den CSS-Bundles. Im abgerufenen Startseiten-HTML waren die Klassen aber nicht eingesetzt, und ohne Browser lässt sich nicht nachweisen, dass das LCP-Element sofort sichtbar ist. Deshalb nicht als Beleg gewertet; Kandidaten für eine Browser-Messung."
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Der Hero steht ab dem ersten Frame, Zeilen steigen aus Masken und die Navigation taucht nach: ein inszenierter Auftritt in 1,2 Sekunden, ganz ohne Ladebildschirm.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "start": "CSS-@keyframes mit fill-mode both direkt an den Elementen, starten beim ersten Rendern; kein JS, kein window.load",
   "zeilen": "@keyframes steigen { from { transform: translateY(110%) } } · 900 ms · cubic-bezier(0.22, 1, 0.36, 1) · Versatz 80 ms (animation-delay: calc(var(--i) * 80ms)), 4 Zeilen (Kicker + 3 Zeilen h1)",
   "masken": "Wrapper .maske { display: block; overflow: hidden; padding-bottom: .06em; margin-bottom: -.06em } stehen im HTML, kein JS-Split",
   "nebenelemente": "@keyframes auftauchen { from { opacity: 0; transform: translateY(12px) } } · 600 ms · cubic-bezier(0.22, 1, 0.36, 1) · Verzögerung: Marke 200, Navigation 260, Anfrage-Knopf 320, Lead 360, CTA 440, Bildunterschrift 520, Als-Nächstes-Karte 600 ms",
   "gesamt_ms": 1200,
   "variante_lcp_steht": "Hero-Bild (LCP-Element) ohne jede Animation, nur Text und Nebenelemente bewegen sich",
   "variante_clip": "Bildrahmen @keyframes oeffnen { from { clip-path: inset(0 0 98% 0) } to { clip-path: inset(0 0 0 0) } } · 1100 ms · cubic-bezier(0.76, 0, 0.24, 1); Bild darin scale 1.08 → 1 · 1100 ms · cubic-bezier(0.22, 1, 0.36, 1)",
   "gegenprobe_preloader": "nur zum Vergleich (so nicht): Overlay mit Zähler 0 → 100 in 1800 ms (cubic-bezier(0.65, 0, 0.35, 1), @property --n), Wischen clip-path inset(0) → inset(0 0 100% 0) 700 ms ab 1800 ms; Inhalte erst ab 2100 ms, Bild opacity 0 → 1 in 300 ms linear → LCP ≈ 2400 ms",
   "telefon": "--tempo: 0.65 unter 760 px Breite, alle Dauern und Verzögerungen × 0,65 → Gesamt 780 ms",
   "bild": "<img fetchpriority=\"high\" decoding=\"async\" width height>, kein loading=lazy; Folgeprojekt-Bild lädt per requestIdleCallback im Hintergrund",
   "schrift_ersatz": "@font-face 'Instrument Sans Ersatz': local('Arial'), local('Liberation Sans'); size-adjust 102.6%; ascent-override 94.5%; descent-override 24.4%; line-gap-override 0% (gemessen gegen Liberation Sans, Schnitt 400); Webfonts mit font-display: swap",
   "neustart_demo": "Klasse .halt setzt animation: none, Layout erzwingen (offsetWidth), Klasse wieder entfernen"
  },
  "ausloeser": "laden",
  "touch": "Kein Hover nötig: das Intro läuft beim Laden. Unter 760 px steht das Bild (3:2) unter dem Text, Navigation wird zu „Menü“, Gesamtdauer etwa 780 ms. Knopf „Nochmal“ spielt das Intro erneut, Umschalter mit 36 px hohen Knöpfen.",
  "reduziert": "Keine Animation: alle Inhalte stehen ab dem ersten Frame, der Ladebildschirm der Gegenprobe entfällt. Zeitachse zeigt nur den LCP-Zeitpunkt, die Werte-Anzeige nennt den Modus.",
  "korrekturen": {
   "beschreibung": "Kein blockierender Ladebildschirm: Das HTML liefert die Hero-Inhalte sofort sichtbar aus. Die Eröffnungsanimation läuft per CSS-@keyframes ab dem ersten Rendern, nicht erst nach JavaScript oder window.load. Headline-Zeilen steigen aus Masken, das Hero-Bild öffnet sich auf Wunsch per clip-path, die Navigation taucht nach. Das LCP-Element (Hero-Bild oder H1) wird nie mit opacity: 0 oder display: none versteckt. Es bewegt sich höchstens per Transform oder Clip, oder es steht von Anfang an und nur Nebenelemente animieren. Bilder, die später gebraucht werden, laden während des Intros im Hintergrund.",
   "warum_es_wirkt": "Die Seite wirkt inszeniert, aber niemand wartet. Der Inhalt ist sofort lesbar, die Bewegung ist Zugabe und kein Vorhang. Weil das LCP-Element sichtbar bleibt, misst der Browser einen frühen Largest Contentful Paint. Laut Shopify verbesserte das Entfernen von Fade-ins am LCP-Element den LCP in einzelnen Fällen um 3 bis 6 Sekunden.",
   "wann_einsetzen": "Als Standard für jede Seite, die ein Intro möchte. Besonders bei Seiten, die über Suchmaschinen gefunden werden oder verkaufen sollen: Portfolio, Shop, Agentur, Produktseite.",
   "wann_nicht": "Wenn vor der ersten Interaktion wirklich schwere Assets nötig sind, etwa eine 3D-Szene oder ein Video. Dann besser eine Ladeszene mit echtem Fortschritt (webgl-ladeszene-fortschritt).",
   "varianten": [
    "Reines CSS-Keyframe-Intro, das mit dem ersten Paint startet",
    "LCP-Element steht sofort, nur Nebenelemente animieren",
    "Clip-Path-Reveal statt Opacity-Fade für das Hero-Bild, ab dem ersten Frame minimal sichtbar",
    "Start aus pagereveal: Inhalte nur in Browsern verstecken, die das Event unterstützen"
   ],
   "umsetzung": "Zeilen: .maske > span { display: block; animation: steigen .9s cubic-bezier(.22, 1, .36, 1) both; animation-delay: calc(var(--i) * 80ms) } mit @keyframes steigen { from { transform: translateY(110%) } }. Die Masken-Wrapper (overflow: hidden) stehen im HTML statt per JS-Split, so läuft alles ohne JavaScript. Bild-Reveal: @keyframes oeffnen { from { clip-path: inset(0 0 98% 0) } } mit 1,1 s cubic-bezier(.76, 0, .24, 1). Das Bild ist so ab dem ersten Frame minimal sichtbar. Wie Chrome Clip-Animationen für den LCP bewertet, ist nicht dokumentiert. Deshalb mit Lighthouse oder dem Performance-Panel der DevTools gegenprüfen. Das LCP-Bild bekommt fetchpriority=\"high\" und kein loading=\"lazy\". Fallstrick Webfonts: font-display: swap mit einer Ersatzschrift, deren Metrik per size-adjust und ascent-override angeglichen ist, sonst springt die Headline.",
   "mobil": "Gleicher Ablauf, nur kürzer: Gesamtdauer etwa 800 ms.",
   "reduzierte_bewegung": "Die Animation entfällt, alles steht sofort. Guter Diagnosetest nach Shopify: LCP mit und ohne reduzierte Bewegung vergleichen. Ist der Wert ohne Animation deutlich besser, bremst das Intro.",
   "barrierefreiheit": "Alle Inhalte stehen sofort im DOM und sind lesbar. Kein Overlay, kein Fokus-Trap. Die Masken-Wrapper ändern die Lesereihenfolge nicht."
  },
  "geprueft": "31.10.2026",
  "notiz": "Hero eines erfundenen Designstudios (Studio Feldhaus, Freiburg). Umschalter: „LCP steht“ (Bild ohne Animation), „Clip-Reveal“ (inset 98 % → 0) und eine bewusst falsche Gegenprobe mit Ladebildschirm. Eine Zeitachse zeigt Intro-Dauer und LCP-Zeitpunkt je Variante, dazu der echte, per PerformanceObserver gemessene LCP der Demo. Die Vorführung wechselt die drei Varianten in Schleife. Alle Animationen sind reines CSS und laufen auch ohne JavaScript; JS steuert nur Umschalter, Neustart und Zeitachse. Bilder 01.11.2026: eigene Bilder statt Portfolio. Zugang 02.11.2026: --leise Alpha .56 → .66 (5,3:1 auf Pult-Grund #e5e1d9). Kontrastmodus: Knöpfe mit Rahmen ButtonText."
 }
}
