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 zastosujesz względną składnię kolorów, aby zmienić przezroczystość koloru, musisz utworzyć właściwości niestandardowe dla kanałów koloru (zwykle HSL) i złożyć 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, zapoznaj się z tym wyzwaniem GUI (dotyczy to niemal wszystkich materiałów wymienionych poniżej).

Omówienie składni

Celem składni względnej kolorów jest umożliwienie pobrania koloru z innego koloru. Kolor podstawowy jest nazywany kolorem źródłowym. Jest to kolor występujący po nowym słowie kluczowym from. Przeglądarka konwertuje ten pierwotny kolor, rozdzielając go na części, które będą dostępne jako zmienne do użycia w nowej definicji koloru.

Widoczny jest diagram przedstawiający składnię rgb(od zielonego r g b / alfa), ze strzałką kierującą się u góry koloru zielonego na początek funkcji RGB. Strzałka jest podzielona na 4 strzałki wskazujące odpowiednią zmienną. 4 strzałki są czerwone, zielone, niebieskie i alfa. Czerwony i niebieski mają wartość 0, zielony – 128, a alfa – 100%.

Na poprzednim diagramie widać, że kolor początkowy green jest konwertowany na przestrzeń kolorów nowego koloru, przekształcony w indywidualne liczby reprezentowane przez zmienne r, g, b i alpha, które są następnie używane bezpośrednio jako wartości nowego koloru rgb().

Na tym obrazie widać podział, proces i zmienne, ale nie ma na nim zmiany koloru. Kolor zmienia się z powrotem na kolor 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, czyli koloru, który zainspiruje kolejny kolor.

Konwersja kolorów

Mówiąc prościej, konwertuje kolor zielony na kanały R, G i B, aby można było go użyć 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 wybranym formacie.

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

Praca w preferowanej przestrzeni 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 określonymi 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 zamiany koloru niż z preferencjami. Preferencja dotyczy wyników, a nie formatu kolorów ani typów kanałów. Będzie to znacznie 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 czas na zmodyfikowanie zmiennych i zmodyfikowanie danych wyjściowych, tak aby różniły się od danych wejściowych.

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

Teraz jest granatowy. Odcień został podwojony, przybrany odcień 120 i przekształcony w 240, co całkowicie zmienia kolor. Spowoduje to zmianę barwy na kole kolorów, co pozwoliło w prosty sposób zastosować cylindryczną przestrzeń kolorów, np. 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 można znaleźć w tej kolekcji Codepen.

Rozjaśnianie koloru

Przestrzenie kolorów OKLCH, OKLAB, XYZ lub sRGB dają najbardziej przewidywalne efekty z rozjaśnieniem 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. Spowoduje to przesunięcie niebieskiego światła na biały o 25%.

.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, lecz 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 ilości

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 obniżać nasycenie o określoną ilość, możesz zmniejszyć nasycenie 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. Przestrzenie kolorów, w których występuje wartość chroma, umożliwiają autorom zwiększanie intensywności kolorów, niż jest to możliwe.

.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. Przykład ze wstępu do tego artykułu. Jeśli nie udało Ci się go znaleźć, dobrze opisuje on przestrzeń, w której występuje.

Dostosowywanie przezroczystości według wartości

.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 częsta funkcja korekty kolorów, która występuje w bibliotekach kolorów. Jednym ze sposobów jest konwersja 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));
}

Uzupełnianie koloru

Jeśli nie chcesz odwrócić koloru, ale raczej go uzupełnić, użyj obrotu barwy. Wybierz przestrzeń barw, która oferuje barwę jako kąt, a następnie użyj calc(), aby obrócić barwę o żądaną wartość. Wyznaczenie dopełnienia koloru odbywa się przez obracanie o połowę obrotu. W tym przypadku aby uzyskać wynik, możesz dodać lub usunąć h kanał 180.

.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);
}

skontrastowanie jaśniejszego koloru.

Klasa .well-contrasting-lighter-color demonstruje też L* z delta 60%. Ponieważ kolor źródłowy jest jasny (ma wysoką wartość jasności), z kanału jasności odjęto 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. Ze względu na dużą liczbę dostępnych przestrzeni kolorów ten model jest szczególnie przydatny i potężny. 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ą i ciemnoś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 uzupełniających, triadyczne palety kolorów to przeciwstawne, ale harmonijne obroty barwy podstawowej. Kiedy kolor uzupełniający znajduje się po przeciwnej stronie koloru, na przykład w prostej linii narysowanej przez środek koła kolorów, palety triadyczne mają postać trójkąta linii, gdzie 2 kolory są równomiernie obrócone od koloru podstawowego. Aby to zrobić, obróć barwę 120deg.

Jest to lekkie uproszczenie teorii kolorów, ale wystarczy, aby zapoznać się z bardziej złożonymi paletami triadycznymi.

: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 tetradzkie to cztery kolory równomiernie podzielone na koło kolorów, tworząc paletę bez wyraźnej wartości dominującej. 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 tylko niewielkie uproszczenie tej teorii kolorów, ale wystarczy, aby opanować bardziej złożone palety tradycyjne.

: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.

Ten przykład zmniejsza jasność o 10% na każdą próbkę, a także obraca ją 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. Zmiana wynosi o 5% lub 5 stopni, czyli znacznie bardziej subtelnie niż w przykładzie powyżej, więc trzeba dobrze przemyśleć, dlaczego tablica wyników może mieć dowolny odcień z taką elegancją.

Pamiętaj, aby zmienić odcień za pomocą suwaka pod tabelą wyników, i sprawdź, 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))
  );
}