Składnia kolorów względnej CSS

Tworzenie nowych kolorów na podstawie kanałów i wartości innego koloru.

Adam Argyle
Adam Argyle

W Chrome 119 dostępna jest bardzo zaawansowana funkcja kolorów z CSS Color Level 5. Składnia kolorów względnych ułatwia manipulowanie kolorami w CSS, oferując autorom i projektantom możliwości:

Zanim zaczniesz używać względnej składni koloru, musisz utworzyć właściwości niestandardowe dla kanałów koloru (zwykle HSL) i połączyć je w ostateczny kolor oraz ostateczny wariant koloru. Oznacza to zarządzanie dużą liczbą elementów o różnych kolorach, co może szybko stać się uciążliwe.

:root {
  --brand-hue: 300deg;
  --brand-saturation: 75%;
  --brand-lightness: 50%;

  --brand-hsl:
    var(--brand-hue)
    var(--brand-saturation)
    var(--brand-lightness);

  --brand-color: hsl(var(--brand-hsl));

  /* all this work just so I can set the opacity to 50% in a variant */
  --brand-color-variant: hsl(var(--brand-hsl) / 50%);
}

Po użyciu względnej składni kolorów możesz utworzyć kolor marki za pomocą dowolnej przestrzeni barw lub składni, której potrzebujesz, oraz utworzyć wariant o połowie krycia za pomocą znacznie mniejszej ilości kodu. Dzięki temu łatwiej też zrozumieć zamysł twórców stylów i systemu.

:root {
  --brand-color: hsl(300deg 75% 50%);
  --brand-color-variant: hsl(from var(--brand-color) h s l / 50%);
}

Z tego posta dowiesz się, jak uczyć się składni i wykonywać typowe manipulacje kolorami.

Jeśli wolisz filmy, większość informacji z tego artykułu znajdziesz w tym wyzwaniu dotyczącym interfejsu graficznego.

Omówienie składni

Celem składni koloru względnego jest umożliwienie wyprowadzenia koloru z innego koloru. Kolor podstawowy to kolor źródłowy, który pojawia się po nowym słowie kluczowym from. Przeglądarka konwertuje ten kolor do postaci składowych i zaoferuje te części jako zmienne do użycia w nowej definicji koloru.

Wyświetla się diagram składni rgb(from green r g b / alpha) ze strzałką wychodzącą z góry zielonego koloru i zakrzywioną w kierunku początku funkcji rgb. Strzałka dzieli się na 4 strzałki, które wskazują odpowiednie zmienne. 4 strzałki są czerwone, zielone, niebieskie i alfa. Czerwony i niebieski mają wartość 0, zielony – 128, a alfa – 100%.

Powyższy diagram pokazuje, jak oryginalny kolor green jest przekształcany w przestrzeni barw nowego koloru, a następnie zamieniany na poszczególne liczby reprezentowane przez zmienne r, g, balpha, które są następnie używane bezpośrednio jako wartości nowego koloru rgb().

Obraz ten pokazuje podział, proces i zmienne, ale nie zmienia koloru. Zmienne są przywracane do koloru bez zmian, w rezultacie czego kolor pozostaje zielony.

Słowo kluczowe from

Pierwszą częścią składni, którą należy poznać, jest część from <color> dodawana do określenia koloru. Pojawia się ona tuż przed określeniem wartości. Oto przykład kodu, w którym dodano tylko blok from green bezpośrednio przed wartościami w bloku rgb().

.syntax-introduction_same-colors {
  color: green;
  color: rgb(0 128 0);
  color: rgb(from green r g b);    /* result = rgb(0 128 0) */
}

Kluczowe słowo from, gdy jest pierwszym parametrem w notacji funkcyjnej, zamienia definicję koloru na kolor względny. Po słowie kluczowym from CSS oczekuje koloru, kolor, który będzie inspirować następny kolor.

Konwersja kolorów

Mówiąc prościej, konwertuje zielony na kanały r, g i b, aby można było użyć go w nowym kolorze.

rgb(from green r g b)           /* r=0 g=128 b=0 */
rgb(from rgb(0 128 0) r g b);   /* r=0 g=128 b=0 */

Kolory z właściwości niestandardowych

Czytanie rgb from green jest bardzo przejrzyste i łatwe do zrozumienia. Dlatego właściwości niestandardowe i względna składnia kolorów tak dobrze się uzupełniają, ponieważ dzięki nim możesz odkryć tajemnicę koloru from. Zwykle nie musisz też znać formatu koloru właściwości niestandardowej, ponieważ tworzysz nowy kolor w dowolnym formacie.

rgb(from rgb(255 105 180) r g b) /* ????? */
rgb(from var(--hotpink) r g b)   /* clear */

Praca w preferowanym modelu kolorów

Możesz wybrać przestrzeń barw z dopasowaną notacją kolorów.

rgb(from hsl(120 100% 25%) r g b)     /*  r=0   g=128  b=0    */
hsl(from hsl(120 100% 25%) h s l)     /*  h=120 s=100% l=25%  */
hwb(from hsl(120 100% 25%) h w b)     /*  h=120 w=0%   b=50%  */
lch(from hsl(120 100% 25%) l c h)     /*  l=46  c=68   h=134  */

Składnia koloru względnego zawiera ten krok konwersji; kolor po from jest konwertowany na przestrzeń barw zgodnie z danymi na początku koloru względnego. Dane wejściowe i wyjściowe nie muszą być takie same, co jest bardzo wygodne.

Możliwość wyboru przestrzeni barw jest również przydatna, ponieważ wybór przestrzeni barw jest zwykle bardziej związany z typem zmiany koloru niż z preferencjami. Preferencja dotyczy wyników, a nie formatu kolorów ani typów kanałów. Będzie to dużo bardziej zrozumiałe w sekcjach przedstawiających przypadki użycia, ponieważ różne przestrzenie barw są odpowiednie do różnych zadań.

Mieszanie, dopasowywanie, pomijanie i powtarzanie zmiennych

Coś dziwnego, ale ekscytującego w tej składni: zmiennych nie trzeba umieszczać w kolejności i można je powtarzać.

rgb(from green g g g)    /* rgb(128 128 128) */
rgb(from green b r g)    /* rgb(0 0 128) */
rgb(from green 0 0 g)    /* rgb(0 0 128) */

Nieprzezroczystość jako zmienna

Składnia zawiera też przezroczystość jako zmienną o nazwie alpha. Jest to opcja, która występuje po / w notacji kolorów funkcjonalnych.

rgb(from #00800080 r g b / alpha)             /* alpha=50% */
rgb(from rgba(0,128,0,.5) r g b / alpha)      /* alpha=50% */
rgb(from rgb(0 128 0 / 50%) r g b / alpha)    /* alpha=50% */

Używanie calc() lub innych funkcji CSS na zmiennych

Do tej pory kolor zielony był tworzony wielokrotnie. Poznaj składnię, zapoznaj się ze ścieżkami konwersji i destrukturyzacją. Teraz możesz zmodyfikować zmienne i zmienić dane wyjściowe, aby nie były takie same jak dane wejściowe.

green                              /*  h=120 s=100% l=25%  */
hsl(from green calc(h * 2) s l)    /*  h=240 s=100% l=25%  */

Teraz jest granatowy. Barwa została podwojona, co oznacza, że z poziomu 120 zmieniono ją na 240, całkowicie zmieniając kolor. To spowodowało obrót barwy na kole barw. Ten sprytny trik jest bardzo prosty dzięki cylindrycznym przestrzeniom barw, takim jak HSL, HWB, LCH i OKLCH.

Aby wizualnie sprawdzić wartości kanałów, dzięki czemu możesz uzyskać prawidłowe wyniki bez zgadywania lub zapamiętywania specyfikacji, użyj tego narzędzia wartości kanałów w względnej składni kolorów. Pokazuje ona wartość każdego kanału na podstawie określonej przez Ciebie składni, dzięki czemu wiesz, z jakimi wartościami możesz pracować.

Sprawdzanie obsługi przeglądarki

@supports (color: rgb(from white r g b)) {
  /* safe to use relative color syntax */
}

Przypadki użycia i demonstracje

Podane niżej przykłady i przypadki użycia mają wiele alternatywnych składni, które dają podobne lub takie same wyniki. Różnice wynikają z przestrzeni barw i kanałów, które oferują.

Ponadto w wielu przykładach zobaczysz korekty kolorów z językowymi opisami byto. Zmiana koloru by to względna zmiana koloru, czyli zmiana, która wykorzystuje wartość zmiennej i wprowadza korektę na podstawie jej bieżącej wartości. Zmiana koloru to to bezwzględna zmiana koloru, czyli zmiana, która nie wykorzystuje wartości zmiennej, a zamiast tego określa zupełnie nową wartość.

Wszystkie wersje demonstracyjne znajdziesz w tej kolekcji Codepen.

Rozjaśnianie koloru

Przestrzenie kolorów OKLCH, OKLAB, XYZ i sRGB zapewniają najbardziej przewidywalne wyniki przy rozjaśnianiu kolorów.

Rozjaśnienie o określoną wartość

W tym przykładzie .lighten-by-25 kolor blue jest konwertowany na OKLCH, a następnie kolor niebieski jest rozjaśniany przez zwiększenie kanału l (jasność) przez pomnożenie bieżącej wartości przez 1.25. W ten sposób jasność koloru niebieskiego staje się o 25% jaśniejsza.

.lighten-by-25 {
  background: oklch(from blue calc(l * 1.25) c h);
}

rozjaśnienie do określonej wartości,

W tym przykładzie .lighten-to-75 nie wykorzystuje kanału l do rozjaśniania blue, tylko całkowicie zastępuje tę wartość wartością 75%.

.lighten-to-75 {
  background: oklch(from blue 75% c h);
}

przyciemniać kolor,

Te same przestrzenie barw, które są skuteczne w rozjaśnianiu koloru, świetnie nadają się też do jego przyciemniania.

przyciemnić o określoną wartość,

W tym przykładzie .darken-by-25 kolor niebieski jest konwertowany na przestrzeń OKLCH, a następnie przyciemniany przez zmniejszenie wartości kanału l (jasność) o 25% przez pomnożenie tej wartości przez .75. W ten sposób kolor niebieski staje się o 25% ciemniejszy.

.darken-by-25 {
  background: oklch(from blue calc(l * .75) c h);
}

przyciemnianie do określonej wartości,

W tym przykładzie .darken-to-25 nie wykorzystuje kanału l do przyciemnienia obrazu w przypadku blue, lecz całkowicie zastępuje tę wartość wartością 25%.

.darken-to-25 {
  background: oklch(from blue 25% c h);
}

Nasycenie koloru

Nasycenie według kwoty

W tym przykładzie .saturate-by-50 używa wartości shsl(), aby zwiększyć nasycanie orchid o względną wartość 50%.

.saturate-by-50 {
  background: hsl(from orchid h calc(s * 1.5) l);
}

nasycenie do określonej wartości;

W tym przykładzie .saturate-to-100 nie wykorzystuje kanału s z hsl(), ale zamiast tego określa pożądaną wartość nasycenia. W tym przykładzie nasycenie jest zwiększone do 100%.

.saturate-to-100 {
  background: hsl(from orchid h 100% l);
}

Odbarwianie

Desaturate by an amount

W tym przykładzie .desaturate-by-half używa s z hsl(), aby zmniejszyć nasycenie indigo o połowę.

.desaturate-by-half {
  background: hsl(from indigo h calc(s / 2) l);
}

Desaturate to a specific value

Zamiast zmniejszać nasycenie o określoną wartość, możesz zmniejszyć je do określonej wartości. W tym przykładzie .desaturate-to-25 tworzy nowy kolor na podstawie indigo, ale nasycenie ustawia na 25%.

.desaturate-to-25 {
  background: hsl(from indigo h 25% l);
}

Chroma Boost

Ten efekt jest podobny do nasycenia koloru, ale różni się od niego w kilku aspektach. Po pierwsze, jest to zmiana chroma, a nie saturation, ponieważ przestrzenie barw, które mogą zwiększyć zakres dynamiczny, nie używają nasycenia. Przestrzeń barw chroma obsługuje większy zakres dynamiczny, co pozwala autorom zwiększyć żywotność kolorów jeszcze bardziej niż przy pomocy nasycenia.

.increase-chroma {
  background: oklch(from orange l calc(c + .1) h);
}

Dostosowywanie przezroczystości koloru

Utworzenie wersji koloru półprzezroczystego jest jednym z najczęstszych dostosowań kolorów w systemach projektowania. Jeśli nie widzisz tego przykładu, zajrzyj do wprowadzenia w tym artykule. Znajdziesz tam bardzo dobry opis przestrzeni problemu.

Dostosowywanie przezroczystości o określoną wartość

.decrease-opacity-by-25 {
  background: rgb(from lime r g b / calc(alpha / 2));
}

Dostosowanie przezroczystości do określonej wartości

.decrease-opacity-to-25 {
  background: rgb(from lime r g b / 25%);
}

Odwrócenie koloru

Odwrócenie kolorów to powszechna funkcja korekty kolorów dostępna w bibliotekach kolorów. Jednym ze sposobów jest przekształcenie koloru na RGB, a następnie odjęcie od 1 wartości każdego kanału.

.invert-each-rgb-channel {
  background: rgb(from yellow calc(255 - r) calc(255 - g) calc(255 - b));
}

Dopełnienie koloru

Jeśli nie chcesz odwrócić koloru, ale raczej go uzupełnić, użyj obrotu barwy. Wybierz przestrzeń barwową, która oferuje barwę jako kąt, a następnie użyj calc(), aby obrócić barwę o żądaną wartość. Aby znaleźć dopełnienie koloru, należy obrócić o pół obrotu. W tym przypadku możesz dodać lub odjąć od kanału h wartość 180, aby uzyskać wynik.

.complementary-color {
  background: hsl(from blue calc(h + 180) s l);
}

Kontrast kolorów

Aby uzyskać odpowiednie współczynniki kontrastu kolorów, rozważ użycie metody L&mid (Lstar). Używa on (w przybliżeniu) jednolicie postrzegalnej jasności (L) z LCH i OKLCH w calc(). W zależności od tego, czy kierujesz reklamy do odbiorców o niskim, średnim czy wysokim kontraście, różnica między L&M a M wynosi około 40, 50 lub 60.

Ta technika sprawdza się w przypadku każdego odcienia w LCH lub OKLCH.

Kontrast z ciemniejszym kolorem

Zajęcia .well-contrasting-darker-color pokazują L* z delta 60. Ponieważ kolor źródłowy jest ciemny (niska jasność), do kanału jasności dodawana jest wartość 60% (0,6). Ta technika służy do znajdowania dobrze kontrastujących, ciemnych kolorów tekstu o tym samym odcieniu na jasnym tle.

.well-contrasting-darker-color {
  background: darkred;
  color: oklch(from darkred calc(l + .60) c h);
}

Kontrast z jaśniejszym kolorem

Klasa .well-contrasting-lighter-color pokazuje również L* z różnicą 60%. Ponieważ kolor źródłowy jest jasny (ma wysoką wartość jasności), z kanału jasności odjęto wartość 0,60.

.well-contrasting-lighter-color {
  background: lightpink;
  color: oklch(from lightpink calc(l - .60) c h);
}

Palety kolorów

Składnia kolorów względnych bardzo dobrze sprawdza się w tworzeniu palet kolorów. Jest szczególnie przydatna i skuteczna dzięki dużej liczbie dostępnych przestrzeni barw. Wszystkie podane przykłady używają modelu OKLCH, ponieważ kanał jasności jest niezawodny, a kanał odcienia może być obracany bez efektów ubocznych. Ostatni przykład pokazuje połączenie korekt jasności i obrotu odcienia w celu uzyskania bardziej interesującego efektu.

Otwórz przykładowy kod źródłowy i spróbuj zmienić --base-color, aby zobaczyć, jak dynamiczne są te palety. To świetna zabawa.

Jeśli wolisz filmy, na kanale YouTube znajdziesz szczegółowe informacje o tworzeniu palet kolorów w CSS za pomocą modelu OKLCH.

Palety monochromatyczne

Paleta monochromatyczna to paleta, w której wszystkie kolory mają ten sam odcień, ale różnią się jasnością. Kolor środkowy jest kolorem źródłowym palety, a po obu stronach znajdują się 2 warianty jaśniej i ciemniejszej.

:root {
  --base-color: deeppink;

  --color-0: oklch(from var(--base-color) calc(l + .20) c h); /* lightest */
  --color-1: oklch(from var(--base-color) calc(l + .10) c h);
  --color-2: var(--base-color);
  --color-3: oklch(from var(--base-color) calc(l - .10) c h);
  --color-4: oklch(from var(--base-color) calc(l - .20) c h); /* darkest */
}
Wypróbuj wiele palet utworzonych za pomocą względnej składni koloru i OKLCH

Open Props to biblioteka bezpłatnych zmiennych CSS, która zawiera palety kolorów utworzone za pomocą tej strategii i umożliwia ich łatwe używanie dzięki importowaniu. Wszystkie są też tworzone na podstawie koloru, który możesz dostosować. Wystarczy, że wybierzesz kolor, a program wygeneruje paletę.

Palety analogiczne

Obracanie odcienia jest bardzo proste w przypadku modeli OKLCH i HSL, więc tworzenie analogicznej palety kolorów nie stanowi problemu. Obróć odcień o wartość, która daje pożądany efekt, i zmień kolor podstawowy. Zobacz, jak przeglądarka tworzy nowe palety.

:root {
  --base-color: blue;

  --primary:   var(--base-color);
  --secondary: oklch(from var(--base-color) l c calc(h - 45));
  --tertiary:  oklch(from var(--base-color) l c calc(h + 45));
}

Palety triadyczne

Podobnie jak w przypadku kolorów dopełniających, paleta triadyczna to przeciwstawne, ale harmonijne obroty barwy podstawowej. Kolory komplementarne znajdują się po przeciwnej stronie koloru, jak prosta na kole barwnym, a palety triadyczne są jak trójkąt linii, który znajduje 2 kolory równomiernie odchylone od koloru bazowego. Aby to zrobić, obróć odcień 120deg.

Jest to lekkie uproszczenie teorii kolorów, ale wystarczy, aby zachęcić Cię do korzystania z bardziej złożonych palet triadycznych.

:root {
  --base-color: yellow;
  --triad-1: oklch(from var(--base-color) l c calc(h - 120));
  --triad-2: oklch(from var(--base-color) l c calc(h + 120));
}

Palety tetrady.

Palety tetradyczności to 4 kolory równomiernie rozmieszczone na kole barw, tworzące paletę bez wyraźnej dominującej wartości. Możesz też pomyśleć o tym jak o 2 parach kolorów uzupełniających. Przy odpowiednim użyciu może ona być bardzo przydatna.

To lekkie uproszczenie teorii kolorów, ale wystarczy, aby rozpocząć pracę z bardziej złożonymi paletami tetradycznymi.

:root {
  --base-color: lime;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) l c calc(h + 90));
  --color-3: oklch(from var(--base-color) l c calc(h + 180));
  --color-4: oklch(from var(--base-color) l c calc(h + 270));
}

Monochromatyczne z niewielkim przesunięciem odcienia

Wielu ekspertów od kolorów zna ten trik. Problem w tym, że monochromatyczna skala kolorów może być dość nudna. Rozwiązaniem jest dodanie do każdego nowego koloru mniejszego lub większego obrotu barwy w miarę zmiany jasności.

W tym przykładzie zmniejszamy jasność każdego odcienia o 10%, a także obracamy odcień o 10 stopni. Efektem jest paleta od różu do indygo, która płynnie przechodzi w kolor gradientu.

:root {
  --base-color: deeppink;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) calc(l - .10) c calc(h - 10));
  --color-3: oklch(from var(--base-color) calc(l - .20) c calc(h - 20));
  --color-4: oklch(from var(--base-color) calc(l - .30) c calc(h - 30));
  --color-5: oklch(from var(--base-color) calc(l - .40) c calc(h - 40));
}
Wypróbuj tę tabelę wyników utworzoną za pomocą OKLCH i rotacji odcieni

Strategię tę stosuje interfejs tabeli liderów. Każdy element listy śledzi swój indeks w dokumencie jako zmienną o nazwie --i. Ten indeks jest następnie używany do dostosowywania chromatyczności, jasności i odsłonięcia. Korekta wynosi tylko 5% lub 5 stopni, co jest znacznie mniej widoczne niż w przypadku przykładu z czerwonego, więc trzeba mieć bystry wzrok, aby zauważyć, dlaczego ta tabela wyników może być w dowolnym odcieniu.

Pamiętaj, aby zmienić odcień za pomocą suwaka pod tabelą wyników, i zobacz, jak względna składnia kolorów tworzy piękne momenty kolorystyczne.

li {
  --_bg: oklch(
    /* decrease lightness as list grows */
    calc(75% - (var(--i) * 5%))

    /* decrease chroma as list grows */
    calc(.2 - (var(--i) * .01))

    /* lightly rotate the hue as the list grows */
    calc(var(--hue) - (var(--i) + 5))
  );
}