# CSS @property: liukuvärien ja ominaisuuksien animointi

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

Liukuvärit eivät tue siirtymiä, koska selain ei voi sekoittaa kuvaa toiseksi. Anna mukautetulle ominaisuudelle tyyppi, niin rajoitus poistuu. Näin @property toimii valmiiden koodiesimerkkien avulla.

## The short version

- CSS @property rekisteröi mukautetulle ominaisuudelle syntaksin, periytymissäännön ja alkuarvon, jotka kertovat selaimelle arvon tyypin.
- Selain ei voi tehdä siirtymää suoraan liukuvärille, koska background-image ei interpoloidu. Liukuvärin sisällä käytetty tyypitetty mukautettu ominaisuus voi kuitenkin interpoloitua.
- Tyypit <color>, <angle>, <percentage> ja <length> animoituvat pehmeästi. Yleistä *-syntaksia käyttävä ominaisuus vain vaihtuu arvosta toiseen.
- Nykyiset Chrome, Edge, Safari ja Firefox tukevat @property-sääntöä. Sitä sivuuttavat selaimet näyttävät liukuvärin ilman liikettä.
- Taustassa käytetyn mukautetun ominaisuuden animointi maalaa elementin uudelleen joka ruudulla. Pidä animoitu alue maltillisena ja kunnioita prefers-reduced-motion-asetusta.

**CSS @property** rekisteröi mukautetun ominaisuuden tyypin. Selain tietää silloin, että `--angle` sisältää kulman tai `--tint` värin. Kun tyyppi on tiedossa, selain voi interpoloida kahden arvon välillä. Voit siis tehdä siirtymiä ja animaatioita asioille, joita CSS ei muuten liikuta: liukuvärin väreille, kulmille ja väripisteen paikalle. Ilman rekisteröintiä mukautettu ominaisuus on vain merkkijono, joka voi ainoastaan hypätä arvosta toiseen.

## Miksi liukuvärit eivät itsessään tue siirtymiä

Kokeile asetusta `transition: background 0.4s` painikkeessa, jonka hover-tila vaihtaa yhden `linear-gradient()`-arvon toiseen. Mikään ei pehmene, vaan uusi liukuväri ilmestyy heti. Liukuvärit ovat kuvia, ja määrittely pitää `background-image`-ominaisuutta interpoloimattomana. Selain ei siis voi sekoittaa kuvaa toiseksi.

Tavallinen kiertotapa on suurentaa taustaa ja liu’uttaa sitä `background-position`-ominaisuudella. Useimmat [animoidut CSS-liukuvärit](https://gradiently.design/fi/guide/css-animated-gradient) tehdään näin. Se toimii, mutta liikuttaa vain muuttumatonta liukuväriä. Et voi vaihtaa väriä, kääntää kulmaa tai siirtää pistettä. Rekisteröidyt ominaisuudet muuttavat tämän: animoitava kohde on kuvan sijaan sen sisällä oleva tyypitetty luku tai väri. Selain laskee liukuvärin joka ruudulla uudelleen nykyisen arvon pohjalta.

### Rekisteröimätön --tint

- Tallennetaan tunnisteiden merkkijonona
- Siirtymä hyppää puolivälissä
- Periytyy oletusarvoisesti
- Virheellinen arvo rikkoo määrittelyn laskentavaiheessa

### Rekisteröity @property-säännöllä

- Tulkitaan oikeaksi väriksi
- Siirtymät interpoloituvat pehmeästi
- Valitset periytymisen itse
- Virheellinen arvo palautuu alkuarvoon

## @property-säännön syntaksi

`@property`-säännössä on kolme kuvaajaa. `syntax` kertoo sallitun arvotyypin, `inherits` sen, saavatko lapsielementit arvon, ja `initial-value` antaa arvon, kun mikään muu ei aseta sitä. Kaikki kolme tarvitaan, paitsi että `initial-value` voidaan jättää pois syntaksin ollessa `*`. Jos vaadittu osa puuttuu tai on väärä, selain sivuuttaa koko säännön ilmoittamatta siitä.

```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%;
}
```

Kolme rekisteröityä ominaisuutta: väri, kulma ja pisteen paikka. Rekisteröi ne kerran tyylitiedoston ylimmällä tasolla.

Alkuarvon täytyy olla laskennallisesti riippumaton eli käytännössä absoluuttisissa yksiköissä. `0deg`, `40%`, `12px` ja heksavärit käyvät, mutta `2em` tai `var(--x)` eivät. Animoinnissa haluat yleensä asetuksen `inherits: false`. Se säästää selaimelta arvon välittämisen elementtipuussa alaspäin.

| Syntaksi | Animoituu pehmeästi | Sopii käyttöön |
| --- | --- | --- |
| `<color>` | Kyllä | Liukuvärien värit, teemavaihdokset |
| `<angle>` | Kyllä | Lineaariset kulmat, kartioliukuvärin pyöritys |
| `<percentage>` | Kyllä | Väripisteiden paikat, koot |
| `<length>` | Kyllä | Säteittäiset koot, siirtymät |
| `<number>` | Kyllä | Peittävyysarvot, kertoimet |
| `<integer>` | Kyllä, kokonaislukujen askelin | Laskurit, porrastetut efektit |
| `*` | Ei, arvo vaihtuu kerralla | Kaikki, mitä et animoi |

Liukuvärityössä olennaiset syntaksit. Voit myös hyväksyä useita, kuten `'<length> | <percentage>'`, tai listan merkillä `+`.

## Animoi liukuvärin väriä hover-tilassa

Tämä on pienin hyödyllinen esimerkki. Painike käyttää `--tint`-arvoa toisena värinään, ja hover-tila muuttaa vain sitä. Koska ominaisuus on rekisteröity väriksi, siirtymä violetista koralliin pehmenee äkillisen vaihdon sijaan.

```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;
}
```

Siirtymä nimeää itse mukautetun ominaisuuden. transition: background ei tekisi tässä mitään.

- Lepotila: --tint on violetti: `linear-gradient(120deg, #1e1b4b 0%, #7c3aed 100%)`
- Siirtymän puolivälissä: `linear-gradient(120deg, #1e1b4b 0%, #bb56b9 100%)`
- Hover: --tint on koralli: `linear-gradient(120deg, #1e1b4b 0%, #fb7185 100%)`

Saman painikkeen kolme ruutua. Keskimmäinen väri on olemassa vain siksi, että selain osaa interpoloida rekisteröityä väriä.

Lisää painikkeiden toteutustapoja löytyy [CSS-liukuväripainikkeista](https://gradiently.design/fi/guide/css-gradient-button) ja [CSS-liukuvärien hover-efekteistä](https://gradiently.design/fi/guide/css-hover-gradient).

## Pyöritä kartioliukuvärireunusta

Suosittu `@property`-käyttötapa on reunus, joka näyttää kiertävän kortin ympäri. [Kartioliukuväri](https://gradiently.design/fi/guide/css-conic-gradient) alkaa kulmasta, joten sen rekisteröinti ja animointi arvosta `0deg` arvoon `360deg` pyörittää värejä. Työn tekevät kaksi taustaa: kortin väri rajattuna täytelaatikkoon ja kartioliukuväri rajattuna reunuslaatikkoon.

```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; }
}
```

Toista ensimmäinen väri lopussa, niin 360deg- ja 0deg-arvojen kohtaamiskohtaan ei jää saumaa.

Kartiorengas kulmassa 0deg: `conic-gradient(from 0deg, #22d3ee, #7c3aed, #f472b6, #22d3ee)`

Sama liukuväri kuin reunuksessa. Kun --angle kasvaa, rengas kääntyy ja kortin ympärillä näkyvä ohut kaistale liikkuu sen mukana. [CSS-liukuvärireunukset](https://gradiently.design/fi/guide/css-gradient-border) käsittelee liikkumatonta versiota.

## Siirrä väripistettä

Rekisteröity prosenttiarvo antaa väripisteen liukua. Käytä sitä etenemispalkin täyttöön, otsikon yli pyyhkäisevään korostukseen tai vierityksessä nousevaan horisonttiin. Tässä `--stop` siirtää kohtaa, jossa liukuväri muuttuu musteensävystä petrooliksi.

```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%;
}
```

Kaksi samassa paikassa olevaa pistettä muodostaa terävän reunan. Reuna liikkuu --stop-arvon mukana.

## Rekisteröinti JavaScriptistä

`CSS.registerProperty()` tekee saman työn skriptistä. Se on kätevä, kun designjärjestelmä rekisteröi ominaisuutensa ajon aikana tai arvo selviää vasta latauksen jälkeen. Saman nimen rekisteröinti kahdesti aiheuttaa virheen, joten suojaa se.

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

JavaScript-muodossa initialValue kirjoitetaan camelCase-muodossa. Kaikki muu vastaa CSS-sääntöä.

## Selaintuki, vararatkaisut ja suorituskyky

`@property` toimii nykyisissä Chromessa, Edgessä, Safarissa ja Firefoxissa. Firefox lisäsi sen viimeisenä versiossa 128. Tarkista [caniuse](https://caniuse.com/mdn-css_at-rules_property), jos tuet vanhoja laitteita. Sääntöä ymmärtämätön selain käsittelee `--angle`-arvoa tavallisena mukautettuna ominaisuutena. Liukuväri piirtyy edelleen alkuarvollaan, muttei liiku. Se on hyvä vararatkaisu, kunhan paikallaan oleva ruutu näyttää valmiilta.

> **Huomioi uudelleenmaalaus** `background`-ominaisuudessa käytetyn arvon animointi maalaa elementin uudelleen joka ruudulla. Pieni reunus tai painike on kevyt, mutta jatkuvasti animoitu koko näytön pääosio kuluttaa akkua. [CSS-liukuvärien suorituskyky](https://gradiently.design/fi/guide/css-gradient-performance) kertoo seurattavat mittaukset.

1. **Rekisteröi ennen käyttöä** Aseta jokainen `@property`-sääntö ylimmälle tasolle mediakyselyjen ulkopuolelle, niin se pätee kaikkialla.
2. **Käytä tyypitettyjä syntakseja** Valitse `<color>`, `<angle>` tai `<percentage>`. Vältä `*`-syntaksia kaikessa, mitä aiot animoida.
3. **Tee siirtymä ominaisuudelle** Kirjoita `transition: --tint 400ms` ja nimeä mukautettu ominaisuus `background`-ominaisuuden sijaan.
4. **Kunnioita vähennettyä liikettä** Pysäytä toistuvat animaatiot asetuksella `prefers-reduced-motion: reduce`, kuten [vähennetyn liikkeen oppaassa](https://gradiently.design/fi/guide/reduced-motion) kuvataan.
5. **Tarkista liikkumaton ruutu** Poista animaatio käytöstä ja varmista, että lepotilan liukuväri näyttää edelleen harkitulta.

Jos haluat liikettä somejulkaisuihin tai videoon verkkosivun sijaan, Gradientlyn Mark sisältää jo oman valonsa ja hitaan liikkeensä. Prolla viet sen MP4-, WebM- tai GIF-muodossa selaimen tukiessa tallennusta, ilman avainruutujen kirjoittamista. Verkossa `@property` on selkein käytettävissäsi oleva työkalu. [MDN:n dokumentaatio](https://developer.mozilla.org/en-US/docs/Web/CSS/@property) luettelee kaikki kuvaajat.

## FAQ

### Mitä CSS @property tekee?

Se rekisteröi mukautetulle ominaisuudelle tyypin, periytymissäännön ja alkuarvon. Tyypin tunteminen antaa selaimen tarkistaa arvon ja interpoloida sitä siirtymissä ja animaatioissa.

### Voiko CSS-liukuväriä animoida?

Ei suoraan, koska background-image ei interpoloidu. Rekisteröi värit, kulma tai väripisteiden paikat @property-säännöllä, käytä niitä liukuvärin sisällä ja animoi näitä ominaisuuksia.

### Miksi @property-animaationi ei toimi?

Yleensä kuvaaja puuttuu, alkuarvo käyttää suhteellista yksikköä, syntaksi on `*` tai siirtymä nimeää `background`-ominaisuuden mukautetun ominaisuuden sijaan. Virheellinen kuvaaja saa selaimen sivuuttamaan koko säännön.

### Tukeeko Firefox @property-sääntöä?

Kyllä. Firefox lisäsi @property-tuen versiossa 128, joten se toimii nyt kaikissa nykyisissä valtavirran selaimissa.

### Pitäisikö inherits-arvon olla true vai false?

Käytä useimmille animoiduille arvoille false-arvoa. Se pitää arvon siinä elementissä, johon asetat sen, ja vähentää selaimen työtä.
