In der jQuery-Ära nutzten wir .animate() oder .fadeIn() für Hover-Effekte. 2026 ist JavaScript dafür unnötiger Overhead. CSS transition läuft oft auf der GPU, bleibt weich und braucht kein Skript. Dieser Leitfaden zeigt Fade-Hover von der Basis bis zu Galerie-, Button- und WordPress-Praxis, inklusive Barrierefreiheit.
Warum CSS Transitions JavaScript schlagen
- Weniger Main-Thread-Arbeit: Kein Timer, kein Style-Recalc in JS.
- Browser-Optimierung: Der Engine kann Compositor-freundliche Properties priorisieren.
- Weniger Abhängigkeiten: Kein jQuery nur für Opacity.
- Bessere Batterie: Weniger CPU-Wakeups auf Mobilgeräten.
JavaScript bleibt sinnvoll für Scroll-Trigger, gestaffelte Sequenzen oder Zustände, die CSS allein nicht abbildet. Für «Bild wird beim Hover etwas transparenter» ist CSS die richtige Schicht.
Grundlegender Fade-Effekt
Angenommen, ein Bild soll beim Hover leicht abdunkeln.
.hover-image {
opacity: 1;
transition: opacity 0.3s ease-in-out;
}
.hover-image:hover,
.hover-image:focus-visible {
opacity: 0.7;
}Ablauf:
- Start bei
opacity: 1. - Beim Hover oder Tastaturfokus Übergang zu
0.7. - Dauer 0,3 Sekunden mit weichem Easing.
- Rückweg automatisch, wenn der Zustand endet.
:focus-visible ist Pflicht, wenn das Bild oder die Karte fokussierbar ist. Sonst erreichen Tastatur-Nutzer denselben Zustand nicht.
Transition-Eigenschaften im Detail
transition-property
Animierte Eigenschaften immer benennen. all ist bequem und teuer.
/* Gut */
transition-property: opacity;
/* Besser bei Kombi */
transition-property: opacity, transform;
/* Vermeiden */
transition-property: all;transition-duration
| Dauer | Wirkung | Typischer Einsatz |
|---|---|---|
| 150–200 ms | Sehr knapp | Toolbar-Icons |
| 200–300 ms | Natürlich | Buttons, Karten, Bilder |
| 400–600 ms | Langsam | Hero-Übergänge, selten |
transition-timing-function
transition-timing-function: ease-out; /* oft am natürlichsten für Hover */
transition-timing-function: ease-in-out; /* weicher Hin- und Rückweg */
transition-timing-function: linear; /* wirkt mechanisch */ease-out startet zügig und bremst ab. Das passt zu UI-Feedback besser als lineares Tempo.
Kurzschreibweise
/* property | duration | timing | delay */
.card-img {
transition: opacity 0.25s ease-out, transform 0.3s ease-out;
}
.card-img:hover {
opacity: 0.85;
transform: scale(1.03);
}
.button-fade {
transition: opacity 0.2s ease-out 0.05s; /* 50 ms Verzögerung */
}Delay sparsam einsetzen. Auf Listen wirkt gestaffeltes Delay oft unecht; ein gemeinsamer Start wirkt ruhiger.
Fortgeschrittene Hover-Muster
Fade plus leichter Zoom
.card-img {
opacity: 1;
transform: scale(1);
transition: opacity 0.3s ease-in-out, transform 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.card-img:hover,
.card-img:focus-visible {
opacity: 0.9;
transform: scale(1.05);
}transform und opacity sind die sicheren Partner. Vermeide animiertes width, height, top oder margin. Die erzwingen Layout und fühlen sich auf Mittelklasse-Handys ruckelig an.
Bild mit Text-Overlay
.image-container {
position: relative;
}
.image-container img {
display: block;
width: 100%;
opacity: 1;
transition: opacity 0.3s ease-in-out;
}
.image-container .caption {
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
.image-container:hover img,
.image-container:focus-within img {
opacity: 0.65;
}
.image-container:hover .caption,
.image-container:focus-within .caption {
opacity: 1;
}focus-within hält die Beschriftung sichtbar, wenn ein Link in der Karte fokussiert ist. Reines :hover reicht auf Touch-Geräten nicht.
Button-Fade
.btn-ghost {
opacity: 0.85;
transition: opacity 0.2s ease-out, background-color 0.2s ease-out;
}
.btn-ghost:hover,
.btn-ghost:focus-visible {
opacity: 1;
}Hier bleibt der Kontrast im Blick: Opacity darf nicht so weit sinken, dass der Text die Kontrastanforderungen verfehlt.
Barrierefreiheit und Reduced Motion
Nicht jeder will Bewegung. Manche Nutzer melden Übelkeit oder Konzentrationsprobleme.
@media (prefers-reduced-motion: reduce) {
.hover-image,
.card-img,
.image-container img,
.image-container .caption,
.btn-ghost {
transition: none;
}
}Zusätzlich:
- Kontrast der Endzustände prüfen (besonders bei Overlay-Text).
- Keine Information nur im Hover verstecken, die für die Aufgabe nötig ist.
- Touch: erster Tap darf nicht nur «Hover simulieren» und den Klick stehlen.
WordPress: wo der Code hingehört
- Child-Theme
style.cssoderassets/css/hover.css: versioniert, reviewbar. wp_enqueue_stylenur auf Templates mit Galerie: spart Bytes auf dem Rest der Site.- Theme.json / Block-Styles: wenn der Effekt zu einem Block-Pattern gehört.
- Customizer Additional CSS: nur für kurze Hotfixes, nicht für Design-Systeme.
add_action( 'wp_enqueue_scripts', function () {
if ( ! is_singular() ) {
return;
}
if ( ! has_block( 'core/gallery', get_post()->post_content )
&& ! has_block( 'core/image', get_post()->post_content ) ) {
return;
}
wp_enqueue_style(
'theme-hover-fade',
get_stylesheet_directory_uri() . '/assets/css/hover-fade.css',
array(),
'2026.09.20'
);
} );Page-Builder-Globals, die denselben Fade auf jeder URL laden, sind der häufigste Performance-Fehler in Audits.
Typische Fehler
transition: all 1sauf großen Layout-Containern.- Animiertes
height: auto(funktioniert unzuverlässig und teuer). - Hover ohne Focus-Zustand.
- Opacity unter 0,5 auf Fließtext.
- Effekt nur in Inline-Styles im Beitrag, unmöglich zentral zu pflegen.
- Doppelte Transitions in Builder und Theme, die gegeneinander kämpfen.
Galerie-Block in Gutenberg
Der Core-Block core/gallery rendert Bilder in Figure-Elementen. Ziel die inneren img-Tags über den Galerie-Wrapper, nicht über globale img-Selektoren. Sonst erwischt du Logos, Avatare und Produktthumbs auf dem Rest der Seite.
.wp-block-gallery .wp-block-image img {
opacity: 1;
transition: opacity 0.25s ease-out, transform 0.3s ease-out;
}
.wp-block-gallery .wp-block-image a:hover img,
.wp-block-gallery .wp-block-image a:focus-visible img {
opacity: 0.8;
transform: scale(1.02);
}Wenn die Galerie Links auf Attachments setzt, liegt der Focus auf dem Anker. Deshalb :focus-visible am Link, nicht nur :hover am Bild. In Theme-Audits sehe ich oft, dass jemand img:hover global setzt und damit den Header-Logo-Hover kaputt macht. Scope spart Support-Tickets.
Für Lightbox-Plugins gilt dieselbe Regel wie für Affiliate-Skripte: das Fade gehört in dein Theme, die Lightbox behält ihr eigenes Öffnen. Zwei konkurrierende Opacity-Transitionen fühlen sich doppelt und langsam an.
Checkliste in 15 Minuten
- Properties auf
opacity/transformbegrenzen. - Dauer 200–300 ms setzen.
:focus-visibleoder:focus-withinergänzen.prefers-reduced-motionabfangen.- Stylesheet nur dort enqueuen, wo Galerien oder Karten existieren.
- Auf einem realen Telefon tippen und prüfen, dass der erste Tap den Link trifft.
- Kontrast im Hover-Zustand kurz gegenprüfen.
- Galerie-Selektoren auf
.wp-block-gallerybegrenzen, nicht auf alleimg.
Zusammenfassung
CSS-Transitions sind der schlanke Weg zu Fade-Hover. Spezifische Properties, kurze Dauer, Focus-Zustände und Reduced Motion trennen brauchbare UI von Dekoration, die Nutzer stört. Hover-Effekte sind schnell gebaut, kosten aber Rendering-Zeit, sobald sie auf Position oder Größe statt auf transform und opacity laufen.
Wenn solche Details im Theme sauber und barrierearm sitzen sollen, übernehmen wir das in der frontendnahen WordPress-Entwicklung. Für ein kurzes Frontend-Review oder die Einbindung in ein Child-Theme schreib uns über das Kontaktformular.






