Składnia kolorów względnej CSS

Utwórz nowe kolory na podstawie kanałów i wartości innego koloru.

Adam Argyle
Adam Argyle

W Chrome 119 to bardzo zaawansowana funkcja kolorów z poziomu kolorów CSS 5. Składnia kolorów względnych tworzy płynną ścieżkę do manipulacji kolorami w CSS, umożliwiając autorom i projektantom:

Przed względną składnią koloru, aby zmienić przezroczystość koloru, należy utworzyć właściwości niestandardowe dla kanałów koloru (zwykle HSL), a następnie połączyć je z kolorem końcowym i ostatecznym kolorem wariantu. Oznacza to zarządzanie wieloma kolorami, co szybko może 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 względnej składni koloru możesz utworzyć kolor marki z dowolną przestrzenią kolorów lub składnią, a także utworzyć wersję o połowie przezroczystości, używając znacznie mniejszej ilości kodu. Dużo łatwiej jest też odczytać intencje stylu i systemu.

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

W tym poście znajdziesz informacje o składni i pokazanie typowych manipulacji kolorami.

Jeśli wolisz filmy, w tym Wyzwaniu GUI opisujemy prawie cały poniższy artykuł.

Omówienie składni

Celem składni względnej jest umożliwienie wyodrębnienia koloru z innego koloru. Jest to kolor podstawowy, który pojawia się po nowym słowie kluczowym from. Przeglądarka przekonwertuje i oddzieli kolor źródłowy i zaproponuje jego części jako zmienne do użycia w nowej definicji koloru.

Diagram składni rgb(z zielonego r g b / alpha) ze strzałką wystającą z góry zielonego i wychodząca na początek funkcji rgb. Strzałka dzieli się na 4 strzałki wskazujące odpowiednią zmienną. Cztery strzałki: czerwona, zielona, niebieska i alfa. Czerwony i niebieski mają wartość 0, zielony – 128, a alfa – 100%.

Poprzedni diagram pokazuje, jak kolor początkowy green jest konwertowany na przestrzeń kolorów nowego koloru, czyli osobne liczby w postaci zmiennych r, g, b i alpha, które są następnie używane bezpośrednio jako nowe wartości koloru rgb().

Przedstawia on podział, proces i zmienne, ale nie zmienia również koloru. Kolory zmiennych są niezmienione, a w efekcie otrzymujemy nieruchomy kolor zielony.

Słowo kluczowe from

Pierwsza część składni, którą należy poznać, to from <color> umożliwiająca określenie koloru. Należy go wpisać bezpośrednio przed określeniem wartości. Oto przykład kodu, w którym wszystkie dodane elementy to from green, tuż przed określeniem wartości rgb().

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

To słowo kluczowe from, uznawane za pierwszy parametr w notacji funkcjonalnej, zmienia definicję koloru na kolor względny. Po słowie kluczowym from CSS wymaga koloru, który będzie inspiracją dla kolejnego koloru.

Konwersja kolorów

W prostszy sposób konwertuje kanały zielone na r g i r b, aby używać ich 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

Tekst rgb from green jest bardzo zrozumiały i łatwy do zrozumienia. Właśnie dlatego właściwości niestandardowe i względna składnia kolorów doskonale się uzupełniają – pozwalają uwypuklić kolor from. Nie musisz też znać formatu koloru właściwości niestandardowego, 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

Przestrzeń barw możesz wybrać z wybraną funkcjonalną 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  */

Względna składnia koloru zawiera ten krok konwersji. Kolor po from jest konwertowany na przestrzeń kolorów zgodnie z wartością na początku koloru względnego. Nie muszą się do siebie zgadzać dane wejściowe i wyjściowe, co bardzo nas uwolni.

Możliwość wyboru przestrzeni kolorów również jest ciekawa, ponieważ wybór przestrzeni kolorów koncentruje się raczej na rodzajach zmiany kolorów niż na preferencjach. Preferencja zależy od wyników, a nie z formatu kolorów czy typów kanałów. Znacznie to wyjaśnimy w sekcjach opisujących przypadki użycia, ponieważ różne przestrzenie kolorów sprawdzają się w różnych zadaniach.

Mieszanie, dopasowywanie, pomijanie i powtarzanie zmiennych

Ta składnia jest czymś dziwnym, ale ekscytującym – nie trzeba ponownie ułożyć zmiennych w porządku 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) */

Przezroczystość jako zmienna

Przezroczystość podawana w składni jest również podawana w postaci zmiennej o nazwie alpha. Jest opcjonalny i znajduje się po / w funkcjonalnej notacji kolorów.

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żyj calc() lub innych funkcji CSS na zmiennych

Do tej pory nieprzerwanie tworzyliśmy kolor zielony. Poznają składnię, zapoznanie się z krokami konwersji i demontażem struktury. Teraz zmodyfikuj zmienne i zmień dane wyjściowe, 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 na morskich kolorach! Odcień został podwojony (kolor 120 został zmieniony na 240) i całkowicie zmienił jego kolor. W ten sposób obróciliśmy barwę na kole kolorów. W ten sposób uprościliśmy użycie walcowych przestrzeni kolorów, np. HSL, HWB, LCH i OKLCH.

Aby zobaczyć wartości kanałów i szybko wykonać obliczenia bez zgadywania i zapamiętywania specyfikacji, wypróbuj to narzędzie – względne wartości kanałów składni kolorów. Ujawnia on wartość każdego kanału na podstawie określonej przez Ciebie składni, dzięki czemu dokładnie wiesz, jakie wartości możesz wypróbować.

Sprawdź, czy przeglądarka obsługuje

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

Przypadki użycia i prezentacje

W poniższych przykładach i przypadkach użycia wiele alternatywnych składni pozwala uzyskać podobne lub takie same wyniki. Wynikają one z przestrzeni kolorów i kanałów, jakie oferują.

W wielu przykładach widać też korektę kolorów za pomocą funkcji by i to. Zmiana koloru by to względna zmiana koloru, która wykorzystuje wartość zmiennej i dostosowuje ją na podstawie jej bieżącej wartości. Zmiana koloru to jest bezwzględną zmianą koloru, czyli taką, która nie korzysta z wartości zmiennej, tylko określa zupełnie nową wartość.

Wszystkie wersje demonstracyjne znajdziesz w tej kolekcji Codepen.

Rozjaśnianie koloru

Przestrzenie kolorów OKLCH, OKLAB, XYZ lub sRGB zapewniają najbardziej przewidywalne rezultaty podczas rozjaśniania kolorów.

Rozjaśnij o ilość

Ten przykład .lighten-by-25 przyjmuje kolor blue i przekształca go na OKLCH, a następnie rozjaśnia kolor niebieski, zwiększając kanał l (jasności), mnożąc bieżącą wartość przez 1.25. Spowoduje to przesunięcie niebieskiego światła w stronę białego o 25%.

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

Rozjaśnij do określonej wartości

W poniższym przykładzie .lighten-to-75 nie użyto kanału l do rozjaśnienia pola blue, tylko zastępuje on wartość 75%.

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

Przyciemnianie koloru

Te same przestrzenie kolorów są skuteczne w rozjaśnianiu kolorów i doskonale nadają się również do przyciemniania.

Przyciemnij o ilość

W przykładzie poniżej .darken-by-25 kolor niebieski jest konwertowany na OKLCH, a następnie przyciemnia kolor niebieski, zmniejszając kanał l (jasności) o 25%, mnożąc wartość przez .75. Spowoduje to przesunięcie koloru niebieskiego na czarny o 25%.

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

Przyciemnij do określonej wartości

W przykładzie w tym przykładzie .darken-to-25 nie użyto kanału l do przyciemnienia kanału blue, tylko całkowicie zastępuje wartość 25%.

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

Nasycenie koloru

Nasycenie o określoną ilość

W poniższym przykładzie .saturate-by-50 użyto parametru s z kolumny hsl(), aby zwiększyć wibrację parametru orchid o względny 50%.

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

Nasycenie do określonej ilości

W przykładzie poniżej .saturate-to-100 nie jest używany kanał s z protokołu hsl(), tylko wymagana wartość nasycenia. W tym przykładzie nasycenie zostało zwiększone do 100%.

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

Usuwanie nasycenia koloru

Zmniejsz nasycenie o określoną ilość

W poniższym przykładzie .desaturate-by-half użyto parametru s z wartości hsl(), aby zmniejszyć nasycenie obiektu indigo o połowę.

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

Zmniejsz nasycenie do określonej wartości

Zamiast zmniejszyć nasycenie o określoną ilość, możesz zmniejszyć nasycenie do konkretnej żądanej wartości. Poniższy przykład .desaturate-to-25 tworzy nowy kolor na podstawie parametru indigo, ale ustawia nasycenie na 25%.

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

Wzmocnienie kolorów

Ten efekt przypomina nasycenie koloru, ale różni się pod kilkoma względami. Po pierwsze jest to zmiana wartości chroma, a nie saturation, ponieważ przestrzenie kolorów, które można wzmocnić do wysokiego zakresu dynamicznego, nie korzystają z nasycenia. Przestrzenie kolorów z funkcją chroma obsługują wysoki zakres dynamiczny, co pozwala autorom zwiększyć intensywność kolorów, nawet jeśli jest to możliwe.

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

Dostosowywanie przezroczystości koloru

Przygotowanie półprzezroczystej wersji koloru to jedna z najczęstszych zmian kolorystycznych w systemach projektowych. We wstępie tego artykułu znajdziesz przykład, który bardzo dobrze pokazuje problem.

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

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

Ustawianie przezroczystości na określoną wartość

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

Odwrócenie koloru

Odwrócenie kolorów to popularna funkcja korekcji kolorów, którą można znaleźć w bibliotekach kolorów. Jednym ze sposobów osiągnięcia tego celu jest konwersja koloru na RGB, a następnie odejmij wartość każdego kanału od 1.

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

Uzupełnij kolor

Jeśli Twoim celem nie było odwrócenie koloru, ale tylko do niego dodanie, wówczas prawdopodobnie chodzi Ci o rotację barw. Wybierz przestrzeń kolorów, w której odcień występuje jako kąt, a potem użyj funkcji calc(), aby obrócić barwę o odpowiednią wartość. Aby znaleźć uzupełnienie koloru, obróć się o połowę. W takim przypadku możesz dodać lub usunąć kolor z kanału h o 180, aby osiągnąć oczekiwany wynik.

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

Skontrastowanie koloru

Jako metodę uzyskiwania łatwo dostępnych współczynników kontrastu kolorów bierzemy pod uwagę L&midast; (Lstar). Wykorzystuje (w przybliżeniu) perceptycznie jednolity kanał jasności (L) z kanałów LCH i OKLCH w obrębie urządzenia calc(). W zależności od tego, czy kierujesz reklamy na niski, średni czy wysoki kontrast, delta l&midast wynosi około 40, ~50 lub ok. 60.

Ta technika sprawdza się w przypadku wszystkich odcieni w LCH i OKLCH.

Skontrastowanie ciemniejszego koloru

Klasa .well-contrasting-darker-color pokazuje L* z delta równą 60. Jako że kolor początkowy to ciemny kolor (niska wartość jasności), więc do kanału jasności dodawane jest 60% (0,6). Ta technika pozwala uzyskać dobrze kontrastujący, ciemny kolor tekstu na jasnym tle o tym samym odcieniu.

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

Skontrastowanie jaśniejszego koloru

Klasa .well-contrasting-lighter-color wykazuje również L* z różnicą wynoszącą 60%. Kolorem początkowym jest kolor jasnym (o wysokiej wartości), dlatego wartość 0,60 jest odejmowana od kanału jasności.

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

Palety kolorów

Składnia kolorów względnych jest bardzo przydatna przy tworzeniu palet kolorów. Jest to szczególnie przydatne ze względu na liczbę dostępnych przestrzeni kolorów. We wszystkich podanych niżej przykładach użyto OKLCH, ponieważ kanał jasności jest niezawodny, a kanał barwy można obracać bez efektów ubocznych. Ostatni przykład przedstawia połączenie korekt jasności i odcieni, aby uzyskać ciekawszy wynik.

Otwórz przykładowy kod źródłowy tych palet i zmień --base-color, by zobaczyć, jak dynamiczne są te palety. To świetna zabawa.

Jeśli lubisz filmy, chętnie podam Ci szczegółowe informacje o tworzeniu palet kolorów w CSS przy użyciu OKLCH w YouTube.

Palety monochromatyczne

Tworząc paletę monochromatyczną, trzeba stworzyć paletę w tym samym odcieniu, ale z różnymi zmianami jasności i ciemności. Kolor środkowy to kolor źródłowy palety. Są to 2 jaśniejsze i 2 ciemniejsze wersje po obu stronach.

: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 kilka palet kolorów utworzonych ze względnej składni kolorów i przy użyciu OKLCH

Open Props to biblioteka bezpłatnych zmiennych CSS, która udostępnia palety kolorów utworzone z użyciem tej strategii i ułatwia ich użycie podczas importu. Kolory są dostępne w różnych kolorach, które można dostosować do swoich potrzeb.

Palety analogowe

Ponieważ w przypadku OKLCH i HSL rotacja barw jest tak prosta, utworzenie analogicznej palety kolorów nie jest trudne. Zmieniaj odcień o wartość, która Ci odpowiada, i zmień kolor podstawowy. Obserwuj też tworzenie nowych palet przez przeglądarkę.

: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 nakładają się na przeciwne, ale harmonijne rotacje kolorów w przypadku koloru podstawowego. Jeśli kolor uzupełniający znajduje się po przeciwnej stronie koloru, na przykład linia prosta narysowana przez środek koła kolorów, palety triadyczne są jak trójkąty, czyli 2 kolory są równomiernie obrócone względem koloru podstawowego. Aby to zrobić, obróć barwę 120deg.

To jest niewielkie uproszczenie teorii kolorów, ale jeśli Cię to interesuje, wystarczy, że zaczniesz wgłębić się w bardziej złożone palety triadyczne.

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

Palety tetradyczne to 4 kolory równomiernie rozmieszczone wokół koła kolorów, co tworzą paletę bez wyraźnej wartości dominującej. Może to być np. dwie pary dopasowujących się kolorów. Jeśli użyjesz ich w przemyślany sposób, Twoje treści mogą mieć duże znaczenie.

To jest niewielkie uproszczenie teorii kolorów, ale jeśli Cię to interesuje, wystarczy, żeby zainteresować Cię 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 nieznaczną rotacją barw

Wielu ekspertów od koloru trzyma w zanadrzu tę sztuczkę. Problem w tym, że monochromatyczna skala kolorów może być nudna. Rozwiązaniem jest dodanie niewielkiego lub większego natężenia do każdego nowego koloru przy zmianie jasności.

Poniższy przykład zmniejsza jasność o 10% na próbkę i obraca barwę o 10 stopni. W efekcie powstała paleta odcienia różu do indygo, która zdaje się płynnie stapiać się jak gradient.

: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ę tablicę wyników stworzoną za pomocą OKLCH i rotacji odcieni

Tej strategii rotacji odcieni używa się poniższy interfejs tabeli wyników. Każdy element listy śledzi swój indeks w dokumencie jako zmienną o nazwie --i. Indeks ten służy następnie do korygowania kolorów, jasności i kolorów. Zmiana wynosi tylko 5% lub 5 st., czyli jest znacznie bardziej subtelna niż w przykładzie powyższym w przypadku deeppink. Warto więc zwrócić uwagę, dlaczego tablica wyników może być w dowolnym odcieniu i eleganckim.

Pamiętaj o zmianie odcienia za pomocą suwaka pod długim banerem i sprawdzenia, czy składnia kolorów względnych sprawia, że kolory są piękne.

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