# CSS @property: animer gradienter og brugerdefinerede egenskaber

[Canonical HTML page](https://gradiently.design/da/guide/css-property-animation)

Gradienter nægter at lave overgange, fordi browseren ikke kan blande ét billede med et andet. Giv en brugerdefineret egenskab en type, og grænsen forsvinder. Her er, hvordan @property virker, med kode du kan indsætte.

## The short version

- CSS @property registrerer en brugerdefineret egenskab med en syntaks, en arveregel og en startværdi, som fortæller browseren, hvilken type værdi den rummer.
- Browsere kan ikke lave en direkte overgang på en gradient, fordi background-image ikke kan interpoleres, men de kan lave overgange på en typet brugerdefineret egenskab inde i gradienten.
- Typede egenskaber som <color>, <angle>, <percentage> og <length> animerer jævnt; en egenskab med den universelle syntaks * skifter bare mellem værdier.
- @property-reglen understøttes i nuværende Chrome, Edge, Safari og Firefox, og browsere, der ignorerer den, viser blot gradienten uden bevægelse.
- At animere en brugerdefineret egenskab i en baggrund gentegner elementet ved hvert billede, så hold det animerede område beskedent og respekter prefers-reduced-motion.

**CSS @property** registrerer en brugerdefineret egenskab med en type, så browseren ved, at `--angle` rummer en vinkel, eller at `--tint` rummer en farve. Når den kender typen, kan den interpolere mellem to værdier, hvilket betyder, at du kan lave overgange og animere ting, som CSS normalt nægter at flytte: gradientfarver, gradientvinkler og placeringen af et farvestop. Uden registrering er en brugerdefineret egenskab bare en streng, og en streng kan kun hoppe fra den ene værdi til den næste.

## Hvorfor gradienter ikke selv laver overgange

Prøv `transition: background 0.4s` på en knap, hvis hover-tilstand bytter én `linear-gradient()` ud med en anden, og intet glider: den nye gradient springer ind. Gradienter er billeder, og specifikationen behandler `background-image` som ikke-interpolerbar, så browseren har ingen måde at blande ét billede med et andet.

Den sædvanlige omvej er at gøre baggrunden for stor og lade `background-position` glide, hvilket er, hvordan de fleste [animerede CSS-gradienter](https://gradiently.design/da/guide/css-animated-gradient) er bygget. Det virker, men det flytter kun en fast gradient rundt. Du kan ikke ændre en farve, dreje en vinkel eller skubbe et stop af sted. Registrerede egenskaber ændrer det, for det, der animeres, er ikke længere billedet, men et typet tal eller en farve inde i det. Browseren genberegner gradienten ved hvert billede ud fra den aktuelle værdi.

### Uregistreret --tint

- Gemt som en streng af tokens
- Overgange springer halvvejs
- Arves som standard
- En ugyldig værdi ødelægger deklarationen ved beregning

### Registreret med @property

- Fortolkes som en rigtig farve
- Overgange interpolerer jævnt
- Arv er dit valg
- En ugyldig værdi falder tilbage til startværdien

## Syntaksen i @property

En `@property`-regel har tre descriptors. `syntax` siger, hvilken type værdi der er tilladt, `inherits` siger, om børn modtager værdien, og `initial-value` bruges, når intet andet sætter den. Alle tre er påkrævet, bortset fra at `initial-value` kan udelades, når syntaksen er `*`. Mangler en påkrævet del, eller er den forkert, ignorerer browseren hele reglen, uden at sige noget.

```css
@property --tint {
  syntax: '<color>';
  inherits: false;
  initial-value: #7c3aed;
}

@property --angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

@property --stop {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 40%;
}
```

Tre registrerede egenskaber: en farve, en vinkel og en stopposition. Registrer dem én gang, øverst i et stylesheet.

Startværdien skal være beregningsmæssigt uafhængig, hvilket i praksis betyder absolutte enheder: `0deg`, `40%`, `12px` og hex-farver er fine, mens `2em` eller `var(--x)` ikke er. At sætte `inherits: false` er som regel det, du vil til animation, og det sparer browseren for at skubbe værdien ned gennem træet.

| Syntaks | Animerer jævnt | Godt til |
| --- | --- | --- |
| `<color>` | Ja | Gradientfarver, temaskift |
| `<angle>` | Ja | Lineære vinkler, konisk rotation |
| `<percentage>` | Ja | Farvestoppets placering, størrelser |
| `<length>` | Ja | Radiale størrelser, forskydninger |
| `<number>` | Ja | Værdier som opacitet, multiplikatorer |
| `<integer>` | Ja, i hele trin | Tællere, trinvise effekter |
| `*` | Nej, den skifter | Alt, du aldrig animerer |

De syntakser, der tæller i gradientarbejde. Du kan også tillade flere, som `'<length> | <percentage>'`, eller en liste med `+`.

## Animer en gradientfarve ved hover

Det er det mindste nyttige eksempel. Knappen bruger `--tint` som sin anden farve, og hover-tilstanden ændrer kun `--tint`. Fordi egenskaben er registreret som en farve, glider overgangen mellem violet og koral i stedet for at springe.

```css
@property --tint {
  syntax: '<color>';
  inherits: false;
  initial-value: #7c3aed;
}

.button {
  background: linear-gradient(120deg, #1e1b4b 0%, var(--tint) 100%);
  transition: --tint 400ms ease;
}

.button:hover {
  --tint: #fb7185;
}
```

Overgangen nævner selve den brugerdefinerede egenskab. At skrive transition: background ville ikke gøre noget her.

- I hvile: --tint er violet: `linear-gradient(120deg, #1e1b4b 0%, #7c3aed 100%)`
- Halvvejs i overgangen: `linear-gradient(120deg, #1e1b4b 0%, #bb56b9 100%)`
- Hover: --tint er koral: `linear-gradient(120deg, #1e1b4b 0%, #fb7185 100%)`

Tre billeder af samme knap. Den midterste farve findes kun, fordi browseren kan interpolere en registreret farve.

For flere måder at behandle knapper på, se [gradientknapper i CSS](https://gradiently.design/da/guide/css-gradient-button) og [CSS gradient hover-effekter](https://gradiently.design/da/guide/css-hover-gradient).

## Drej en konisk gradientkant

En yndet brug af `@property` er en kant, der ser ud til at rejse rundt om et kort. En [konisk gradient](https://gradiently.design/da/guide/css-conic-gradient) starter fra en vinkel, så ved at registrere vinklen og animere den fra `0deg` til `360deg` drejer farverne rundt. To baggrunde gør arbejdet: kortets farve klippet til padding-boksen og den koniske gradient klippet til border-boksen.

```css
@property --angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

.card {
  border: 2px solid transparent;
  border-radius: 16px;
  background:
    linear-gradient(#0f0b1e, #0f0b1e) padding-box,
    conic-gradient(from var(--angle), #22d3ee, #7c3aed, #f472b6, #22d3ee) border-box;
  animation: spin 6s linear infinite;
}

@keyframes spin {
  to { --angle: 360deg; }
}

@media (prefers-reduced-motion: reduce) {
  .card { animation: none; }
}
```

Gentag den første farve til sidst, så samlingen, hvor 360deg møder 0deg, forsvinder.

Den koniske ring ved 0deg: `conic-gradient(from 0deg, #22d3ee, #7c3aed, #f472b6, #22d3ee)`

Samme gradient, som kanten bruger. Når --angle vokser, drejer ringen, og den tynde stribe rundt om kortet rejser med. [Gradientkanter i CSS](https://gradiently.design/da/guide/css-gradient-border) dækker den statiske version.

## Flyt et farvestop

En registreret procentværdi lader et stop glide. Brug den til en statusfyldning, et højdepunkt, der fejer hen over en overskrift, eller en horisont, der stiger ved scroll. Her flytter `--stop` det punkt, hvor gradienten skifter fra blæk til blågrøn.

```css
@property --stop {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 20%;
}

.meter {
  background: linear-gradient(90deg, #0d9488 0%, #0d9488 var(--stop), #0f172a var(--stop));
  transition: --stop 600ms ease-out;
}

.meter[data-done] {
  --stop: 100%;
}
```

To stop på samme position giver en hård kant, og kanten flytter sig, når --stop ændres.

## Registrering fra JavaScript

`CSS.registerProperty()` gør det samme job fra et script. Det er praktisk, når et designsystem registrerer sine egenskaber under kørsel, eller når en værdi først kendes efter indlæsning. At registrere samme navn to gange kaster en fejl, så beskyt det.

```js
if ('registerProperty' in CSS) {
  try {
    CSS.registerProperty({
      name: '--angle',
      syntax: '<angle>',
      inherits: false,
      initialValue: '0deg',
    })
  } catch {
    // Already registered, which is fine.
  }
}
```

JavaScript-formen bruger initialValue i camelCase. Alt andet svarer til CSS-reglen.

## Browserunderstøttelse, nødløsninger og ydeevne

`@property` virker i nuværende Chrome, Edge, Safari og Firefox; Firefox var den sidste, der tilføjede den, i version 128. Tjek [caniuse](https://caniuse.com/mdn-css_at-rules_property), hvis du understøtter ældre enheder. En browser, der ikke forstår reglen, behandler `--angle` som en almindelig brugerdefineret egenskab, så din gradient tegnes stadig med sin startværdi og bevæger sig bare ikke. Det er en fin nødløsning, så længe det stille billede ser færdigt ud.

> **Husk gentegningen** At animere en egenskab, der bruges i `background`, får browseren til at gentegne elementet ved hvert billede. En lille kant eller knap er billig; en fuldskærms-hero, der animeres uafbrudt, koster batteri. [CSS gradient-ydeevne](https://gradiently.design/da/guide/css-gradient-performance) har de målinger, du skal holde øje med.

1. **Registrer, før du bruger** Læg hver `@property`-regel på øverste niveau, uden for media queries, så den gælder overalt.
2. **Brug typede syntakser** Vælg `<color>`, `<angle>` eller `<percentage>`. Undgå `*` til alt, du har tænkt dig at animere.
3. **Lav en overgang på egenskaben** Skriv `transition: --tint 400ms`, så du nævner den brugerdefinerede egenskab frem for `background`.
4. **Respekter reduceret bevægelse** Stop animationer i loop under `prefers-reduced-motion: reduce`, som beskrevet i [prefers reduced motion](https://gradiently.design/da/guide/reduced-motion).
5. **Tjek det stille billede** Slå animationen fra og sørg for, at hvilegradienten stadig ser bevidst ud.

Hvis den bevægelse, du ønsker, hører hjemme på opslag på sociale medier eller video frem for en webside, bærer en Gradiently-Mark allerede sit eget lys og sin egen langsomme bevægelse, og Pro eksporterer den som MP4, WebM eller GIF, hvor browseren understøtter optagelse, uden at du skriver keyframes. Til alt på nettet er `@property` det reneste værktøj, du har. [MDN-referencen](https://developer.mozilla.org/en-US/docs/Web/CSS/@property) lister hver descriptor.

## FAQ

### Hvad gør CSS @property?

Den registrerer en brugerdefineret egenskab med en type, en arveregel og en startværdi. Når typen er kendt, kan browseren validere værdien og interpolere den i overgange og animationer.

### Kan man animere en CSS-gradient?

Ikke direkte, fordi background-image ikke kan interpoleres. Registrer farverne, vinklen eller stoppositionerne med @property, brug dem i gradienten, og animer de egenskaber i stedet.

### Hvorfor virker min @property-animation ikke?

Som regel mangler der en descriptor, startværdien bruger en relativ enhed, syntaksen er `*`, eller overgangen nævner `background` i stedet for den brugerdefinerede egenskab. Enhver ugyldig descriptor får browseren til at ignorere hele reglen.

### Understøtter Firefox @property?

Ja. Firefox tilføjede @property i version 128, så den virker nu i alle store nuværende browsere.

### Skal inherits være true eller false?

Brug false til de fleste animerede værdier. Det holder værdien på det element, hvor du sætter den, og sparer browseren for ekstra arbejde.
