====== LU06a – CSS Transitions ====== {{:de:modul:m291:learningunits:lu05:theorie:faq-toggle-transistion.gif?nolink|}} ===== CSS Transitions – Grundprinzip ===== Eine CSS Transition animiert den Übergang zwischen zwei Zuständen eines Elements. Sie definieren, **welche Eigenschaft** animiert wird, **wie lange** die Animation dauert und nach welcher **Timing-Kurve**. {{:de:modul:m291:learningunits:lu05:theorie:transition_hover_rect.gif?nolink|}} \\ //Hover-Transition der Hintergrundfarbe// .element { background-color: blue; transition: background-color 400ms ease-in-out; } .element:hover { background-color: red; } Beim Hovern wechselt die Hintergrundfarbe nun nicht abrupt, sondern gleitend über 400 ms von Blau zu Rot. Mehrere Eigenschaften gleichzeitig animieren: .panel { opacity: 0; height: 0; transition: opacity 600ms ease-in-out, height 600ms ease-in-out; } ===== Trigger: Was löst eine Transition aus? ===== Damit eine Transition aktiviert wird, braucht es zwei Dinge: eine **Eigenschaft, die sich ändert**, und ein **Ereignis, das diese Änderung auslöst**. Die häufigsten Trigger in CSS: ^ Trigger ^ Beschreibung ^ | '':hover'' | Cursor befindet sich über dem Element | | '':focus'' | Element ist fokussiert (z.B. per Tab-Taste) | | '':focus-within'' | Element oder eines seiner Kind-Elemente ist fokussiert | | '':active'' | Element wird gerade aktiviert (Maustaste gedrückt) | | '':target'' | URL-Fragment stimmt mit der ''id'' des Elements überein | | **Klasse via JavaScript** | Eine CSS-Klasse wird per ''classList.add/remove/toggle'' geändert | \\ {{:de:modul:m291:learningunits:lu05:theorie:focus_transition_input.gif?nolink| Focus-within Transition}} \\ //Durch Klicken ins Formular-Feld erhält das Element den Fokus -> Ein Trigger für eine Transition der Transparenz.// Der letzte Punkt ist für unser Accordion entscheidend: Wir setzen per JavaScript die Klasse ''open'' – und CSS übernimmt die Animation vollständig. JavaScript steuert den **Zustand**, CSS steuert die **Animation**. ===== Was kann (und was kann nicht) animiert werden? ===== Nicht jede CSS-Eigenschaft lässt sich animieren. Die Grundregel: Eine Eigenschaft ist animierbar, wenn zwischen Start- und Endwert ein **Zwischenwert berechnet werden kann**. **Beispiel:** ''font-size: 12px'' → ''font-size: 24px'' ✅ – jeder Pixelwert dazwischen ist berechenbar. **Gegenbeispiel:** ''font-family: serif'' → ''font-family: monospace'' ❌ – was wäre eine Schriftart-Mitte? ==== Gut animierbare Eigenschaften ==== === transform === ''transform'' ist die am häufigsten eingesetzte Eigenschaft für Transitions. Sie wird direkt von der **GPU** berechnet – das ergibt flüssigere Animationen und belastet den Browser weniger als Layout-Eigenschaften. {{:de:modul:m291:learningunits:lu05:theorie:rotate_scale_rect.gif?nolink|}} .box { transition: transform 400ms ease-out; } .box:hover { transform: scale(1.2) rotate(5deg) translateY(-8px); } Einzelne Transform-Eigenschaften können auch separat animiert werden: .box { transition: scale 300ms ease-out, rotate 300ms ease-in-out, translate 300ms ease-out; } .box:hover { scale: 1.2; rotate: 5deg; translate: 0 -8px; } === Farbe === ''color'', ''background-color'' und ''border-color'' sind häufige Transition-Kandidaten – sie geben bei Interaktion visuelles Feedback, z.B. wenn ein Button beim Hovern die Farbe wechselt. .btn { background-color: steelblue; transition: background-color 250ms ease-in-out; } .btn:hover { background-color: royalblue; } === opacity === Sanftes Ein- und Ausblenden – das Element **bleibt aber im Layout** (es nimmt weiterhin Platz ein). === Weitere animierbare Eigenschaften === ^ Eigenschaft ^ Einsatz ^ | ''width'', ''height'' | Zwischen zwei fixen Werten (z.B. ''0'' → ''200px'') | | ''margin'', ''padding'' | Layout-Animationen | | ''border-radius'' | Formen weich überblenden | | ''box-shadow'' | Elevation-Effekte (z.B. bei Fokus) | | ''filter'' | ''blur()'', ''brightness()'', ''saturate()'' etc. | | ''font-size'', ''letter-spacing'' | Typografische Animationen | ==== Nicht animierbar ==== ^ Eigenschaft ^ Warum nicht? ^ | ''display'' | Kein Mittelwert zwischen ''none'' und ''block'' möglich | | ''font-family'' | Kein Mittelwert zwischen Schriftarten möglich | | ''position'' | Kategoriewechsel, kein kontinuierlicher Übergang | | ''visibility'' | Binärer Wert (sichtbar/unsichtbar) | Eine vollständige Liste animierbarer Eigenschaften: [[https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties|MDN – Animatable CSS properties]] ===== Antworten Ein- und Ausblenden mit 'display' ===== Im ersten Schritt haben wir die Panels mit ''display: none'' / ''display: block'' ein- und ausgeblendet. Das funktioniert – aber es gibt **keinen Übergang**, das Element erscheint und verschwindet abrupt. **Warum lässt sich ''display'' nicht animieren?** CSS Transitions interpolieren zwischen zwei Zahlenwerten. ''display: none'' bedeutet: das Element **existiert im Layout nicht**. Zwischen "existiert nicht" und "existiert" kann kein Mittelwert berechnet werden – eine Transition ist daher logisch nicht möglich. /* ❌ Kein Übergang möglich */ .panel { display: none; transition: display 400ms; /* wirkungslos */ } .panel.open { display: block; /* schaltet sofort um */ } ===== Das Problem: height von 0 zu auto ===== Der einfachste und natürlichste Ansatz wäre: ''height: 0'' → ''height: auto'' (-> auto: der Browser berechnet selbst die Höhe des Elements anhand der Inhalte). Leider funktioniert das **nicht** mit einer Transition: /* ❌ Funktioniert NICHT – Browser kann nicht interpolieren */ .panel { height: 0; overflow: hidden; transition: height 600ms ease-in-out; } .panel.open { height: auto; /* Browser weiss nicht, was das in px bedeutet */ } Der Browser kann zwischen einem fixen Pixelwert (''0'') und dem Schlüsselwort ''auto'' nicht interpolieren – ''auto'' ist kein Zahlenwert, sondern eine Anweisung: "berechne die Höhe selbst". ===== Die moderne Lösung: interpolate-size: allow-keywords ===== Seit 2024 unterstützen moderne Browser eine neue CSS-Eigenschaft, die genau dieses Problem löst: ''interpolate-size: allow-keywords''. Sie erlaubt dem Browser, Übergänge zwischen einem Pixel-Wert und einem CSS-Schlüsselwort wie ''auto'', ''min-content'' oder ''max-content'' zu berechnen. :root { interpolate-size: allow-keywords; /* einmal global definieren */ } Damit funktioniert ''height: 0'' → ''height: auto'' mit einer Transition wie erwartet. ==== CSS-Transitions: Ein- und Ausblenden der Antworten ==== :root { interpolate-size: allow-keywords; } /* Standardmässig versteckt */ .panel { height: 0; opacity: 0; overflow: hidden; transition: height 800ms ease-in-out, opacity 800ms ease-in-out; } /* Sichtbar wenn Klasse 'open' gesetzt */ .panel.open { height: auto; opacity: 1; } Das Öffnen und Schliessen wird weiterhin per JavaScript durch ''classList.add('open')'' / ''classList.remove('open')'' gesteuert – die Animation läuft vollständig in CSS. **Browser-Support:** ''interpolate-size: allow-keywords'' wird aktuell **nur von Chrome/Edge** unterstützt – Safari und Firefox kennen sie noch nicht. In diesen Browsern springt das Panel beim Öffnen abrupt auf ''height: auto'', ohne Animation. Aktuellen Support prüfen: [[https://caniuse.com/mdn-css_properties_interpolate-size|caniuse.com – interpolate-size]] ===== Timing-Funktionen ===== Der dritte Parameter von ''transition'' steuert die Beschleunigungskurve der Animation: ^ Wert ^ Beschreibung ^ | ''ease'' | Langsam starten, beschleunigen, langsam enden (Standard) | | ''ease-in'' | Langsam starten, schnell enden | | ''ease-out'' | Schnell starten, langsam enden – oft natürlicher | | ''ease-in-out'' | Langsam starten und enden, in der Mitte schnell | | ''linear'' | Konstante Geschwindigkeit | | ''cubic-bezier(x,x,x,x)'' | Vollständig selbst definierte Kurve | Im Accordion-Projekt verwenden wir ''ease-in-out'' – das Panel öffnet und schliesst sich jeweils mit einer leichten Verzögerung am Anfang und Ende, was natürlicher wirkt. Interaktives Beispiel mit Beispiel-Code: [[https://css-transitions.vercel.app|Externe Seite erkunden.]] [[https://css-transitions.vercel.app|{{ :de:modul:m291:learningunits:lu05:theorie:screenshot_2026-03-09_at_00.26.55.png?600 |}}]]