I jQuery-tiden ble hover-fade ofte løst med .animate() eller .fadeTo(). I 2026 er det unødvendig for enkle UI-tilstander: nettleseren kan interpolere opacity direkte med CSS. Resultatet er mindre skript, færre layout-thrash-risikoer og en effekt som følger systemets preferanser når du kobler inn prefers-reduced-motion.
Denne artikkelen er en praktisk front-end-oppskrift for WordPress-tema og Gutenberg. Du får en minimal fade på hover, deretter transition versus animation, tastaturvennlig :focus-visible, redusert bevegelse, korrekt wp_enqueue_style, typiske blokk-CSS-feller, og hvorfor compositor-egenskaper holder 60 fps mer forutsigbart enn width eller top.
CSS transitions eller JavaScript for hover-effekter
JavaScript er riktig når tilstanden avhenger av nettverk, skjema-validering eller komplekse sekvenser. For «mus over bilde, demp litt» er CSS raskere å lese og billigere å kjøre.
Konkrete fordeler i praksis:
- Ingen event-lyttere som må ryddes opp i spa-lignende admin-skjermer.
- Nettleseren kan behandle
opacityogtransformpå compositor-tråden når laget er etablert. - Samme regelsett fungerer for musepekere og for fokus når du speiler tilstanden med
:focus-visible. - Du unngår race conditions mellom
mouseenter/mouseleaveog CSS som allerede animerer.
Unntaket er når du må synkronisere med et skriptstyrt lag (for eksempel en tilpasset lightbox som setter aria-hidden). Da kan du fortsatt bruke CSS for selve fade-en og bare bytte en klasse fra JavaScript.
Fade bilde ved hover med CSS opacity
Start med et bilde eller en knapp. Sett startverdien eksplisitt, deklarer hvilken egenskap som skal interpoleres, og endre verdien i :hover.
.hover-image {
opacity: 1;
transition: opacity 0.3s ease-in-out;
}
.hover-image:hover {
opacity: 0.7;
}Hva som skjer steg for steg:
- Elementet er fullt synlig (
opacity: 1). - Ved hover går verdien mot
0.7over 300 ms. - Timing-funksjonen
ease-in-outmyker start og stopp. - Når hover opphører, kjører overgangen tilbake til
1med samme regel.
opacity er en tallverdi mellom 0 og 1. Den påvirker hele elementet inklusive barn. Hvis bare bakgrunnen skal dempes, er background-color med rgba() eller color-mix() ofte mer presist enn å dempe hele kortet.
Transition versus animation
transition og animation er ikke utskiftbare verktøy. Velg etter hva som utløser bevegelsen.
Bruk transition når:
- En egenskap endrer seg mellom to tilstander (hover, fokus, åpen/lukket klasse).
- Du vil at nettleseren skal interpolere fra nåværende verdi til en ny verdi.
- Effekten skal snu midtveis hvis brukeren flytter musen vekk.
Bruk @keyframes / animation når:
- Bevegelsen skal kjøre uten brukerinteraksjon (lasting, forsiktig pulse, intro).
- Du trenger flere nøkkelrammer, forsinkelser per steg, eller
animation-iteration-count. - Tilstanden ikke er en enkel A→B-endring.
/* Transition: drevet av tilstandsendring */
.btn {
opacity: 1;
transition: opacity 0.2s ease-out;
}
.btn:hover {
opacity: 0.85;
}
/* Animation: tidsstyrt sekvens */
@keyframes fade-in-once {
from { opacity: 0; }
to { opacity: 1; }
}
.hero-title {
animation: fade-in-once 0.4s ease-out both;
}En vanlig feil i temaer er å «animere» hover med evig animation og deretter kjempe mot animation-fill-mode. For hover er transition nesten alltid renere.
Hover-effekt med focus-visible for tastatur
:hover alene er utilstrekkelig for tastaturbrukere. Speil den visuelle tilbakemeldingen med :focus-visible, slik at Tab-navigasjon får samme fade uten at hvert museklikk etterlater et synlig fokusring-spor.
.card-media {
opacity: 1;
outline: none;
transition: opacity 0.25s ease, box-shadow 0.25s ease;
}
.card-media:hover,
.card-media:focus-visible {
opacity: 0.75;
}
.card-media:focus-visible {
box-shadow: 0 0 0 3px color-mix(in srgb, CanvasText 40%, transparent);
}Praktiske merknader:
- Bruk
:focus-visible, ikke bare:focus, hvis du vil unngå fokus fokusmarkering etter museklikk i moderne nettlesere. - Sørg for at det fokuserbare elementet faktisk kan motta fokus (
<a>,<button>, ellertabindex="0"med tastaturhåndtering). - Ikke fjern
outlineuten å erstatte den. Fade alene er ikke nok kontrast for fokusindikator.
På berøringsskjermer er :hover sticky i noen nettlesere. Hold fade-en subtil (0.7-0.9), så «låst» hover ikke ser ut som en feil.
Hvordan slå av hover-animasjon med prefers-reduced-motion
Noen brukere har bedt systemet om mindre bevegelse. Respekter det med en media query som kortslutter overganger og animasjoner.
@media (prefers-reduced-motion: reduce) {
.hover-image,
.card-media,
.btn {
transition: none;
animation: none;
}
}Du kan også forkorte varigheten i stedet for å nullstille alt, men for fade på hover er none greit: tilstanden bytter fortsatt, bare uten interpolasjon.
Test i macOS (Tilgjengelighet → Skjerm → Reduser bevegelse) og i Windows (Visuelle effekter / animasjonsinnstillinger). Verifiser at fokusmarkeringen fortsatt er synlig når overgangen er av.
CSS transition-egenskaper forklart
Transition-property
Angi alltid konkrete egenskaper. transition: all er fristende, men den animerer også ting du ikke tenkte på (for eksempel border-width eller font-size fra en annen regel) og koster mer.
/* Foretrekk */
transition-property: opacity, transform;
/* Unngå i UI-komponenter */
transition-property: all;Transition-duration
For grensesnitt ligger typisk 150-300 ms i den sonen der effekten merkes uten å føles treg. Under 100 ms kan se ut som et hardt kutt. Over 400 ms begynner hover å føles tregt på desktop.
Transition-timing-function
ease-out: rask start, myk landing - ofte best på hover-ut.ease-in-out: symmetrisk mykhet - grei på opacity-fade.linear: sjelden ønskelig for UI, mer for fremdriftsindikatorer.cubic-bezier(...): når merkevaren har en egen bevegelseskurve.
Transition-delay
Forsinkelse er nyttig når et underordnet lag skal vente på et overordnet. På enkel bilde-fade er delay vanligvis 0s; ellers føles UI tregt.
CSS transition kortform med flere egenskaper
Kortformen er property duration timing-function delay:
.hover-image {
transition: opacity 0.3s ease-in-out 0s;
}
/* Flere egenskaper */
.card-img {
transition:
opacity 0.25s ease-out,
transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}Hold rekkefølgen konsistent i hele temaet. Når én komponent bruker langt format og en annen kortformat med andre verdier, blir bevegelsesspråket rotete.
Avanserte hover-mønstre uten jQuery
Fade pluss skalering
transform: scale() kombineres godt med opacity fordi begge kan compositor-akselereres.
.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.04);
}Unngå å animere width / height for zoom. Det tvinger layout og paint på hver frame.
Fade på bilde inne i en beholder
Når hover-området er større enn bildet (hele kortet), sett :hover på beholderen:
.image-container img {
opacity: 1;
transition: opacity 0.3s ease-in-out;
}
.image-container:hover img,
.image-container:focus-within img {
opacity: 0.7;
}:focus-within dekker tastaturfokus på lenken inne i kortet.
WordPress: enqueue stilarket riktig
Legg ikke fade-CSS som en tilfeldig <style>-blokk i header.php hvis du kan unngå det. Bruk temaets enqueue-API slik at avhengigheter, versjonering og lasting blir forutsigbare.
<?php
declare(strict_types=1);
add_action('wp_enqueue_scripts', static function (): void {
$theme_version = wp_get_theme()->get('Version');
$css_path = get_theme_file_path('assets/css/hover-fade.css');
$css_ver = file_exists($css_path) ? (string) filemtime($css_path) : $theme_version;
wp_enqueue_style(
'theme-hover-fade',
get_theme_file_uri('assets/css/hover-fade.css'),
[],
$css_ver
);
});Hvorfor dette mønsteret:
filemtimegir cache-bust når filen endres, uten manuell versjonsbump hver gang.- Handle
theme-hover-fadekan dequeques eller overstyres i child themes. - Du unngår duplikater hvis en blokk eller et plugin også prøver å injisere samme regler.
For blokk-temaer (FSE) kan du fortsatt enqueue et lite utility-ark, eller legge utilitariske klasser i theme.json der det passer. Store hover-regler med media queries hører fortsatt hjemme i CSS-filer.
Hvis effekten bare trengs på én mal, beting enqueue med is_singular() / is_page_template() for å holde kritisk CSS mindre.
Hvorfor fade ikke virker i Gutenberg-blokker
Gutenberg endrer DOM-strukturen mer enn klassiske maler. Fade som «virket i Classic» feiler ofte av disse grunnene:
1. Feil selector på wrapper
Blokker pakkes ofte i .wp-block-image, .wp-block-group eller figure/figcaption. En regel som treffer img:hover direkte treffer ikke når hover skjer på lenke-wrapper rundt bildet.
/* For snevert i mange blokk-oppsett */
.wp-block-image img:hover {
opacity: 0.7;
}
/* Mer robust */
.wp-block-image a:hover img,
.wp-block-image a:focus-visible img,
.wp-block-image figure:hover img {
opacity: 0.7;
}2. Inline styles og content-bilder
Bildestiler satt i editoren (style="width:...") konkurrerer ikke nødvendigvis med opacity, men !important i tema-reset eller plugin-CSS kan det. Hold specificiteten lav og konsistent; unngå !important for fade.
3. Additional CSS versus blokk-stylesheet
«Tilleggs-CSS» i Tilpasning er greit for prototyper. For produksjon: egen fil via enqueue, eller blokk-spesifikk stil registrert med wp_enqueue_block_style, slik at reglene lastes bare der blokken brukes.
4. Interaktivitet og nested blokker
Gruppe-blokker med lenker inni kan trigge hover på forelder mens fokus er på barn. Test både mus og Tab. :focus-within på kort-wrapper løser mange av disse tilfellene.
5. Editor versus frontend
Canvas i editoren laster ikke alltid temaets frontend-CSS. Hvis kunden «ikke ser fade i editor», er det forventet med mindre du også enqueue’er stilene via enqueue_block_assets eller add_editor_style. Dokumenter skillet: effekt på live-side, ikke nødvendigvis i canvas.
Hvilke CSS-egenskaper er raske å animere
Når du animerer egenskaper som trigger layout (width, height, top, left, margin) eller dyr paint (box-shadow på enorme flater uten lag), risikerer du jank på mobil.
Foretrekk for fade / micro-interaction:
opacitytransform(translate, scale, rotate)
Vær forsiktig med:
filter: blur()på store bilder (kan være dyrt)- animerte
box-shadow-verdier på hele viewport-seksjoner transition: all
Du trenger sjelden will-change: opacity på hvert bilde i et rutenett. will-change reserverer minne; bruk det midlertidig på elementer som faktisk animerer ofte, eller stol på at nettleseren promoterer laget under transition.
Mål med Performance-panelet: se etter lange frames under hover på en liste med mange kort. Hvis layout thrashing dukker opp, er det nesten alltid feil egenskap som animeres.
Feilsøking når fade ikke synes
- Sjekk at start- og sluttverdi faktisk er forskjellige.
- Bekreft at
transitionsitter på base-regelen, ikke bare på:hover(ellers mangler retur-overgang i noen tilfeller avhengig av hvordan reglene skrives). - Se etter andre regler som setter
transition: noneglobalt. - Kontroller
prefers-reduced-motioni OS. - I WordPress: bekreft at stilarket er enqueue’t (View Source / Network) og at selector matcher den renderte blokk-DOM-en.
Oppsummering
CSS-overganger er den moderne, vedlikeholdbare måten å gjøre hover-fade på i WordPress-temaer.
Ta med deg:
- Animer
opacity(og gjernetransform), ikke layout-egenskaper. - Bruk
transitionfor tilstand,animationfor tidsstyrte sekvenser. - Speil hover med
:focus-visible/:focus-within. - Respekter
prefers-reduced-motion. - Enqueue CSS via
wp_enqueue_style, og tilpass selectorer til Gutenberg-wrappers. - Hold varighet rundt 0,2-0,3 s for UI.
Med det på plass trenger du ikke jQuery for en dempet bilde-hover - bare tydelige tilstander og et stilark som faktisk lastes. Når du senere utvider til flere komponenter, gjenbruk samme varighet og timing-funksjon i hele temaet, så føles grensesnittet konsekvent for både musebrukere og tastaturnavigasjon.







