Hover-Effekte und CSS-States sind Pseudo-Klassen-basierte Stiländerungen und Animationen, die interaktive Elemente in Verbindung mit Benutzeraktionen (Hover, Fokus, Klick) visuell kommunizieren.
Was sind Hover-Effekte & CSS-States?
CSS-States sind die visuellen Erscheinungsbilder eines Elements in verschiedenen Interaktionszuständen. Für jeden Zustand stellt CSS Pseudo-Klassen bereit, die unterschiedliche Stile definieren lassen.
Die wichtigsten interaktiven States:
:hover– Mauszeiger befindet sich über dem Element:focus– Element hat Tastaturfokus:focus-visible– Fokus NUR bei Tastaturnavigation sichtbar:active– Element wird gerade geklickt/gedrückt:visited– Bereits besuchter Link:disabled– Deaktiviertes Element:checked– Ausgewählte Checkbox oder Radio:placeholder-shown– Eingabefeld zeigt Platzhaltertext:valid/:invalid– Formularvalidierung
Hover-Effekte sind eine Untergruppe dieser States und beschränken sich auf den :hover-Zustand. Sie sind die häufigste Form bewusst gestalteter Animation im Web.
Erklärung
Grundlagen: Transition + Pseudo-Klasse
```css / Basis-Pattern / .element { / Ausgangszustand / color: #333; background: transparent;
/ Transition auf dem Ausgangszustand deklarieren / transition: color 0.2s ease, background 0.2s ease; }
.element:hover { / Zielzustand / color: #0078ff; background: rgba(0, 120, 255, 0.06); } ```
Warum Transition auf dem Ausgangselement, nicht auf :hover? Die Transition gilt für beide Richtungen (Hover-ein UND Hover-aus). Wenn man sie nur auf :hover definiert, springt das Element beim Verlassen sofort zurück.
Button-States vollständig gestalten
```css .btn { padding: 12px 24px; background: #0078ff; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: 600;
/ Transition für alle States / transition: background 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease, opacity 0.2s ease; }
/ Hover: Feedback und Einladung zum Klick / .btn:hover { background: #0060cc; transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0, 120, 255, 0.3); }
/ Active: physisches Drücken simulieren / .btn:active { transform: translateY(0); box-shadow: none; background: #0050aa; }
/ Focus-visible: nur bei Tastaturnavigation sichtbar / .btn:focus-visible { outline: 3px solid #0078ff; outline-offset: 3px; }
/ Disabled: klar als inaktiv markiert / .btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; pointer-events: none; } ```
Komplexere Hover-Effekte mit Pseudo-Elementen
Unterstrich-Animation:
```css .link { position: relative; text-decoration: none; color: inherit; }
.link::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 2px; background: currentColor; transform: scaleX(0); transform-origin: right; transition: transform 0.3s ease; }
.link:hover::after { transform: scaleX(1); transform-origin: left; } ```
Füll-Effekt von innen:
```css .btn-outline { position: relative; border: 2px solid #0078ff; color: #0078ff; background: transparent; overflow: hidden; z-index: 0; transition: color 0.3s ease; }
.btn-outline::before { content: ''; position: absolute; inset: 0; background: #0078ff; transform: scaleX(0); transform-origin: left; transition: transform 0.3s ease; z-index: -1; }
.btn-outline:hover { color: white; }
.btn-outline:hover::before { transform: scaleX(1); } ```
Magnetischer Hover-Effekt (JavaScript):
```javascript document.querySelectorAll('.magnet-btn').forEach(btn => { btn.addEventListener('mousemove', (e) => { const rect = btn.getBoundingClientRect(); const xMitte = rect.left + rect.width / 2; const yMitte = rect.top + rect.height / 2; const xOffset = (e.clientX - xMitte) 0.3; const yOffset = (e.clientY - yMitte) 0.3;
btn.style.transform = translate(${xOffset}px, ${yOffset}px); });
btn.addEventListener('mouseleave', () => { btn.style.transform = 'translate(0, 0)'; btn.style.transition = 'transform 0.5s elastic'; });
btn.addEventListener('mouseenter', () => { btn.style.transition = 'transform 0.1s ease'; }); }); ```
Karten-Hover mit 3D-Kippeffekt
```javascript document.querySelectorAll('.karte-3d').forEach(karte => { karte.addEventListener('mousemove', (e) => { const rect = karte.getBoundingClientRect(); const x = (e.clientX - rect.left) / rect.width; // 0 bis 1 const y = (e.clientY - rect.top) / rect.height; // 0 bis 1
const rotX = (y - 0.5) -15; // -7.5 bis 7.5 Grad const rotY = (x - 0.5) 15;
karte.style.transform = perspective(800px) rotateX(${rotX}deg) rotateY(${rotY}deg) scale(1.02); });
karte.addEventListener('mouseleave', () => { karte.style.transform = 'perspective(800px) rotateX(0) rotateY(0) scale(1)'; }); }); ```
``css .karte-3d { transition: transform 0.1s ease; transform-style: preserve-3d; } ``
In der Praxis
Barrierefreiheit als Leitprinzip: Das häufigste Problem bei Hover-Effekten ist das Vergessen des :focus-visible-States. Nutzer, die per Tastatur navigieren (inklusive aller Nutzer ohne Maus), sehen sonst keine Interaktions-Rückmeldung.
```css / Modern: focus-visible statt focus / .btn:focus-visible { outline: 3px solid #0078ff; outline-offset: 2px; }
/ Niemals entfernen ohne Alternative: / / .btn:focus { outline: none; } ← NIEMALS / ```
Touch-Geräte haben kein Hover. :hover-Effekte werden auf Touch-Geräten teilweise simuliert (letzter Touch), können aber störend wirken:
``css @media (hover: hover) { /* Nur für Geräte mit echter Hover-Fähigkeit */ .btn:hover { transform: translateY(-2px); } } ``
Timing-Empfehlungen:
- Hover-Eingang: 150–250 ms (reagiert sich direkt)
- Hover-Ausgang: 200–350 ms (sanftes Ausklingen)
- Active-State: 80–150 ms (muss sehr direkt wirken)
Vergleich & Abgrenzung
| State | Auslöser | Hauptzweck |
|---|---|---|
:hover | Mausbewegung über Element | Interaktivitätssignal |
:focus-visible | Tastatur-Tab-Navigation | Accessibility-Pflicht |
:active | Mausklick / Touch | Klick-Feedback |
:disabled | disabled-Attribut | Inaktivität signalisieren |
Häufige Fragen (FAQ)
Sollte ich `:focus` oder `:focus-visible` verwenden? :focus-visible für modernes Web. Es zeigt den Fokusring nur bei Tastatur- und Nicht-Maus-Navigation, nicht bei Mausklicks – das ist das gewünschte Verhalten für die meisten UI-Elemente.
Warum funktioniert mein Hover auf Smartphones? Auf Touch-Geräten löst der erste Tap einen simulierten :hover-State aus (bleibt bis zum nächsten Tap). Nutze @media (hover: hover) um echtes Hover von simuliertem zu unterscheiden.
Kann ich Hover-Effekte auf iOS verhindern? Ja, mit der @media (hover: none) Media Query für Touch-only-Geräte.
Verwandte Einträge
- CSS Transitions – Technische Basis für alle Hover-Animationen
- Micro-Interactions im UI Design – Hover-Effekte im größeren UI-Kontext
- CSS Transforms (2D & 3D) – Transform als häufige Hover-Animation
- Performance-Optimierung bei Web-Animationen – Welche Hover-Properties performant sind
Weiterführend
- MDN: CSS Pseudo-classes (2024) – developer.mozilla.org
- Adam Argyle: :focus-visible Is Here (2021) – web.dev
- Val Head: Designing Interface Animation (2019) – Rosenfeld Media
- Lea Verou: CSS Secrets (2015) – O'Reilly Media
- CSS Tricks: A Complete Guide to CSS Pseudo-classes – css-tricks.com
