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.
Hvorfor CSS transitions slår javascript for hover
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.
Grunnleggende fade med 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 og focus-visible sammen
: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.
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.
Forstå transition-egenskapene
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.
Fullstendig kortform
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.
Gutenberg-blokker: CSS-feller som ødelegger fade
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.
Ytelse: hold deg på compositor-egenskaper
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.







