{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "fullpage-snap-slides",
 "name": "Abschnittsweises Einrasten (Fullpage-Snap)",
 "name_en": "Section snapping / fullpage slides (scroll-snap, GSAP Observer)",
 "kurz": "Fünf Bühnen eines Hotels in Meran: Jeder Scroll-Impuls führt zur nächsten Folie, erst im eingerasteten Zustand treten Text und Bild auf.",
 "kategorie": "Scroll & Section-Animationen",
 "kategorie_slug": "scroll",
 "kategorie_nr": 5,
 "bau_chat": "C2",
 "prioritaet": "C",
 "trendstatus": "abklingend",
 "belegstatus": "quellenbelegt",
 "website_belege": 0,
 "stimmung": [
  "editorial",
  "präzise"
 ],
 "stimmung_roh": [
  "präsentativ",
  "kontrolliert"
 ],
 "technik": [
  "css",
  "gsap",
  "observer",
  "lenis"
 ],
 "technik_gruppen": [
  "css",
  "gsap",
  "lenis"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Jeder Abschnitt füllt den Viewport. Ein Scroll-Impuls führt zum nächsten Abschnitt, die Seite rastet ein. Das geht nativ mit scroll-snap-type oder gekapert: GSAP Observer fängt Wheel und Touch ab und spielt einen zeitbasierten Übergang. Erst im eingerasteten Zustand treten die Inhalte auf, in neuen Browsern per scroll-state(snapped) ganz ohne JavaScript.",
  "warum_es_wirkt": "Die Seite wird zur Präsentation. Jeder Abschnitt ist eine fertig komponierte Bühne, die nie halb angeschnitten erscheint.",
  "wann_einsetzen": "Kurze Kampagnen- und Launch-Seiten, Portfolio-Slideshows, Kiosk-Anwendungen, ein Haus in wenigen Räumen zeigen.",
  "wann_nicht": "Bei Inhalten unterschiedlicher Höhe, langen Seiten und Lesetexten. Viele Nutzer empfinden harte Snaps als bevormundend, besonders wenn sie Preise vergleichen wollen.",
  "varianten": [
   "Native scroll-snap mit mandatory, weicher mit proximity",
   "ScrollTrigger snap: rastet nach dem Scroll-Ende weich ein",
   "GSAP Observer mit eigener Übergangsanimation (Scroll-Jacking)",
   "Lenis snap"
  ],
  "umsetzung": "Nativ: html { scroll-snap-type: y mandatory } section { scroll-snap-align: start; min-height: 100svh }. Inhalte beim Einrasten: section { container-type: scroll-state } und darin @container scroll-state(snapped: y) { … }, sonst eine Klasse per IntersectionObserver. ScrollTrigger: snap: { snapTo: 1 / (n - 1), duration: { min: 0.2, max: 0.6 }, ease: 'power3' }. Observer: Observer.create({ type: 'wheel,touch', wheelSpeed: -1, onUp, onDown, tolerance: 10, preventDefault: true }) und eine Timeline pro Wechsel. Diese Variante nur mit vollständiger Tastatursteuerung (Pfeile, Bild ab, Leertaste, Pos1, Ende).",
  "mobil": "mandatory vermeiden, weil Adressleiste und hohe Inhalte springen. Besser proximity oder gar kein Snap.",
  "reduzierte_bewegung": "Kein Snap. Übergänge ohne Bewegung, Inhalte nur kurz einblenden.",
  "barrierefreiheit": "Scroll-Jacking bricht die Erwartung. Inhalte, die höher als der Viewport sind, werden mit mandatory unerreichbar. Tastatur und Bildschirmleser testen, Abschnitte mit aria-label benennen und eine sichtbare Abschnittsnavigation anbieten."
 },
 "messwerte": {
  "easing": "power3 (GSAP-snap-Default)",
  "dauer_ms": "200–600 snap",
  "stagger_ms": "",
  "distanz": "",
  "sonstiges": "snap delay Default = halbe scrub-Zeit bzw. 0,1",
  "herkunft": "beobachtet",
  "quelle": "https://gsap.com/docs/v3/Plugins/ScrollTrigger/"
 },
 "kurve": {
  "bezier": [
   0.25,
   1,
   0.5,
   1
  ],
  "css": "cubic-bezier(0.25, 1, 0.5, 1)",
  "name": "power3.out",
  "dauer_ms": 200
 },
 "gesehen_bei": [
  {
   "seite": "Chrome Developers – scroll-state(snapped)",
   "url": "https://developer.chrome.com/blog/css-scroll-state-queries",
   "auszeichnung": "",
   "beobachtung": "Slide-Inhalte beim Einrasten animieren, ohne IntersectionObserver.",
   "art": "artikel"
  },
  {
   "seite": "GSAP 3.10 – Observer-Plugin",
   "url": "https://gsap.com/blog/3-10",
   "auszeichnung": "",
   "beobachtung": "Observer für Wheel/Touch/Pointer-Gesten, Basis vieler Fullpage-Slides.",
   "art": "artikel"
  }
 ],
 "tutorials": [
  {
   "titel": "CSS scroll-state() queries",
   "url": "https://developer.chrome.com/blog/css-scroll-state-queries"
  },
  {
   "titel": "GSAP 3.10 (Observer, ScrollSmoother)",
   "url": "https://gsap.com/blog/3-10"
  }
 ],
 "kombinierbar_mit": [
  "theme-farbwechsel-scroll",
  "scroll-fortschritt"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/scroll/fullpage-snap-slides/",
  "meta": "https://cecodesign.de/lab/fundus/scroll/fullpage-snap-slides/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/scroll/fullpage-snap-slides/demo"
 },
 "herkunft": {
  "quelldateien": [
   "scroll.json",
   "patch-belege-3.json"
  ],
  "pruefnotizen": [
   "patch-belege-3.json: Kein Produktionsbeleg gefunden (scroll-snap nur in Swiper-CSS); bleibt C."
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Fünf Bühnen eines Hotels in Meran: Jeder Scroll-Impuls führt zur nächsten Folie, erst im eingerasteten Zustand treten Text und Bild auf.",
  "demo": true,
  "abhaengigkeiten": [
   "gsap@3.15.0",
   "ScrollTrigger@3.15.0",
   "Observer@3.15.0"
  ],
  "werte": {
   "easing": "power3.out = cubic-bezier(0.25, 1, 0.5, 1) für alles Sichtbare",
   "css_snap": "html { scroll-snap-type: y mandatory } · section { scroll-snap-align: start; scroll-snap-stop: always; min-height: 100svh }",
   "touch_snap": "y proximity, scroll-snap-stop: normal",
   "einrasten_inhalt": "@container scroll-state(snapped: y), Fallback Klasse .aktiv per IntersectionObserver (rootMargin -50% 0px -50% 0px)",
   "einblenden": "opacity 0 → 1 und translateY 28 px → 0, 600 ms, Stagger 80 ms",
   "bild": "scale 1.06 → 1, 900 ms, transform-origin 50% 70%",
   "scrolltrigger_snap": "snapTo: nächste Folienkante (Array der Fortschrittswerte), duration { min: 0.2, max: 0.6 } s, delay 0.1 s, ease power3.out",
   "observer": "type wheel,touch · wheelSpeed -1 · tolerance 10 · preventDefault · Wechsel 1000 ms · neue Folie yPercent ±100 → 0 · Innenleben −50 % gegenläufig → 0 · alte Folie 0 → ∓30 %",
   "tastatur_observer": "Pfeil runter/hoch, Bild ab/auf, Leertaste, Pos1, Ende",
   "ui": "150–200 ms cubic-bezier(0.4, 0, 0.2, 1) für Knöpfe und Kopffarbe (400 ms)",
   "vorfuehrung": "Impuls 26 % Viewport in 380 ms (power1.in), 120 ms Pause, Einrasten 600 ms power3.out, alle 2,6 s"
  },
  "ausloeser": "scroll",
  "touch": "Nativ rastet auf Touch nur weich ein (proximity, kein scroll-snap-stop), damit Adressleiste und hohe Inhalte nicht springen. Die Observer-Variante reagiert auf Wischen. Punkt-Navigation entfällt unter 900 px, der Zähler im Kopf bleibt.",
  "reduziert": "Kein Einrasten (scroll-snap-type: none), Variantenwahl gesperrt. Inhalte blenden nur 200 ms linear ein, ohne Versatz und ohne Bild-Skalierung.",
  "korrekturen": {
   "beschreibung": "Jeder Abschnitt füllt den Viewport. Ein Scroll-Impuls führt zum nächsten Abschnitt, die Seite rastet ein. Das geht nativ mit scroll-snap-type oder gekapert: GSAP Observer fängt Wheel und Touch ab und spielt einen zeitbasierten Übergang. Erst im eingerasteten Zustand treten die Inhalte auf, in neuen Browsern per scroll-state(snapped) ganz ohne JavaScript.",
   "warum_es_wirkt": "Die Seite wird zur Präsentation. Jeder Abschnitt ist eine fertig komponierte Bühne, die nie halb angeschnitten erscheint.",
   "wann_einsetzen": "Kurze Kampagnen- und Launch-Seiten, Portfolio-Slideshows, Kiosk-Anwendungen, ein Haus in wenigen Räumen zeigen.",
   "wann_nicht": "Bei Inhalten unterschiedlicher Höhe, langen Seiten und Lesetexten. Viele Nutzer empfinden harte Snaps als bevormundend, besonders wenn sie Preise vergleichen wollen.",
   "varianten": [
    "Native scroll-snap mit mandatory, weicher mit proximity",
    "ScrollTrigger snap: rastet nach dem Scroll-Ende weich ein",
    "GSAP Observer mit eigener Übergangsanimation (Scroll-Jacking)",
    "Lenis snap"
   ],
   "umsetzung": "Nativ: html { scroll-snap-type: y mandatory } section { scroll-snap-align: start; min-height: 100svh }. Inhalte beim Einrasten: section { container-type: scroll-state } und darin @container scroll-state(snapped: y) { … }, sonst eine Klasse per IntersectionObserver. ScrollTrigger: snap: { snapTo: 1 / (n - 1), duration: { min: 0.2, max: 0.6 }, ease: 'power3' }. Observer: Observer.create({ type: 'wheel,touch', wheelSpeed: -1, onUp, onDown, tolerance: 10, preventDefault: true }) und eine Timeline pro Wechsel. Diese Variante nur mit vollständiger Tastatursteuerung (Pfeile, Bild ab, Leertaste, Pos1, Ende).",
   "mobil": "mandatory vermeiden, weil Adressleiste und hohe Inhalte springen. Besser proximity oder gar kein Snap.",
   "reduzierte_bewegung": "Kein Snap. Übergänge ohne Bewegung, Inhalte nur kurz einblenden.",
   "barrierefreiheit": "Scroll-Jacking bricht die Erwartung. Inhalte, die höher als der Viewport sind, werden mit mandatory unerreichbar. Tastatur und Bildschirmleser testen, Abschnitte mit aria-label benennen und eine sichtbare Abschnittsnavigation anbieten."
  },
  "geprueft": "01.11.2026",
  "notiz": "Welt: Rezept boutique-hotel-gastgeber, erfundene Villa Waalhang in Meran-Obermais (Gastgeber Vroni und Lukas Pircher). Newsreader für Headlines, Mona Sans breit für Labels, Farben aus dem Rezept plus Rebgrün. Fünf Folien (Ankommen mit Buchungsleiste, Suite, Garten, Frühstück mit Törggelen, Buchungsübersicht), jede mit eigener SVG-Szene im Bogenfenster. Umschalter: CSS-Snap (Standard, Einblenden per scroll-state), ScrollTrigger-Snap, Observer mit innerer Gegenbewegung (Signatur des Rezepts). Das Rezept führt den Snap nicht, er passt aber als Haus-in-fünf-Räumen-Präsentation. Referenzen: das-stue.com, fogoislandinn.ca, standardhotels.com, juvet.com. AD-Review 01.11.2026: Note 5. Zugang 02.11.2026: --meta #6f716b → #5e605a (5,1:1 auf Sand, 4,9:1 auf Stein), --meta-f der Folie Reb Alpha .72 → .8 (4,9:1), Sprachwahl opacity .7 → .8. Tastatur: .folie:focus-within zeigt die .rein-Inhalte sofort (ohne Einrast-Verzögerung), damit fokussierte Knöpfe nicht unsichtbar sind. Kontrastmodus: Knöpfe mit Rahmen ButtonText."
 }
}
