Tworzenie schematu kolorów

Podstawowy przegląd sposobów tworzenia dynamicznego i konfigurowalnego schematu kolorów

W tym poście chcę pokazać, jak zarządzać wieloma schematami kolorów w CSS. Wypróbuj wersję demonstracyjną.

Demonstracja

Jeśli wolisz film, oto wersja tego posta w YouTube:

Omówienie

Utworzymy system kolorów z uwzględnieniem dostępności za pomocą właściwości niestandardowych i elementu calc(), aby strona internetowa dostosowywała się do preferencji użytkownika, a jednocześnie minimalizowała konieczność tworzenia. Zaczynamy od podstawowego koloru marki i tworzymy system jego wariantów: 2 kolory tekstu, 4 kolory powierzchni i pasujący cień.

W tym przewodniku na początku definiujemy wszystkie kolory dla każdego schematu kolorów. Do zmiany strony są używane dopiero na samym końcu.

Marka

Często kolor marki ma już ustalony i wyświetlany w postaci szesnastkowej lub rgb. Ta praca konkursowa w zakresie interfejsu GUI ma podstawowy kolor marki #0af. Po pierwsze, w przypadku tego systemu kolorów wartość szesnastkowa musi zostać przekonwertowana na hsl.

* {
  --brand: #0af;
  --brand: hsl(200 100% 50%);
}

Aby przedstawić koncepcję przyciemniania lub rozjaśniania koloru marki, powiedzmy o 20%, należy wyodrębnić 3 kanały wartości koloru hsl i do swoich właściwości niestandardowych, na przykład:

* {
  --brand-hue: 200;
  --brand-saturation: 100%;
  --brand-lightness: 50%;
}

CSS może wykonywać operacje na tych właściwościach kolorów, np. calc(var(--brand-lightness) - 20%), aby zmniejszyć wartość jasności o 20%. Ma to kluczowe znaczenie dla stworzenia schematu kolorów, ponieważ CSS może utrzymać wszystkie kolory w tej samej rodzinie barw, dostosowując nasycenie i poziom jasności.

Jasny motyw

Każda wersja koloru będzie oznaczona odpowiednim schematem. W tym przypadku każdy kolor będzie miał dołączony znak -light.

podgląd wyników końcowych w jasnym motywie

Marka

Zaczynamy od koloru marki, aby ponownie utworzyć właściwości --brand-hue, --brand-saturation i --brand-lightness w nawiasie funkcji hsl () (bez wykonywania obliczeń):

* {
  --brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}

Kolory tekstu

Następnie musisz dobrać kolory tekstu. Przy jasnym motywie tekst powinien być bardzo ciemny. Zwróć uwagę, że jasność tych kolorów jest niska i nie przekracza 50%.

* {
  --text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
  --text2-light: hsl(var(--brand-hue) 30% 30%);
}

--text1-light, ponieważ jest bardzo ciemny przy jasności 10%, zachowuje nasycenie 100%, dzięki czemu kolor marki może przebijać przez ciemny granat.

--text2-light nie jest tak ciemny jak pierwszy kolor, co jest dobre, ponieważ jest to kolor dodatkowy. Jest też znacznie mniej nasycony.

Kolory powierzchni

Kolory powierzchni to tła, obramowania i inne powierzchnie ozdobne, na których znajduje się tekst. W motywie jasnym są to jasne kolory, w przeciwieństwie do kolorów tekstu, które są ciemne. Aby utworzyć jasne kolory za pomocą modelu hsl, użyjemy wyższych wartości procentowych w trzeciej wartości jasności. Obniżamy też nasycenie, aby jasnoszary nie były zabarwione.

* {
  --surface1-light: hsl(var(--brand-hue) 25% 90%);
  --surface2-light: hsl(var(--brand-hue) 20% 99%);
  --surface3-light: hsl(var(--brand-hue) 20% 92%);
  --surface4-light: hsl(var(--brand-hue) 20% 85%);
}

Powstały 4 kolory powierzchni, ponieważ kolory dekoracyjne zwykle wymagają większej liczby wariantów w przypadku interaktywnych momentów, takich jak :focus lub :hover, lub tworzenia wyglądu warstw z papieru. W takich sytuacjach warto zastosować przejście z --surface2-light na --surface3-light, aby po najechaniu kursorem na ikonę zwiększyć kontrast (z jasności 99% na 92%, czyli ściemnienie).

Cienie

Cienie w schemacie kolorów są niesamowite, ale dodają efektowi naturalności i pomagają wyróżnić go na tle nierealistycznych cieni na czarnym tle. W tym celu użyjemy właściwości niestandardowej koloru cienia, by była nieznacznie nasycona, ale wciąż bardzo ciemna. Zasadniczo tworzymy bardzo ciemny cień o lekko niebieskim zabarwieniu.

* {
  --surface-shadow-light: var(--brand-hue) 10% 20%;
  --shadow-strength-light: .02;
}

Funkcja --surface-shadow-light nie jest ujęta w ramach funkcji hsl. Dzieje się tak, ponieważ wartość --shadow-strength zostanie połączona, aby uzyskać pewną przezroczystość, a CSS potrzebuje tych elementów, aby wykonać obliczenia. Aby dowiedzieć się więcej, przejdź do sekcji dotyczącej osi czasu.

Jasne kolory razem

Nie musisz szukać, jak powstały jasne kolory, ponieważ wszystkie są w jednym miejscu w pliku CSS.

* {
  --brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
  --text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
  --text2-light: hsl(var(--brand-hue) 30% 30%);
  --surface1-light: hsl(var(--brand-hue) 25% 90%);
  --surface2-light: hsl(var(--brand-hue) 20% 99%);
  --surface3-light: hsl(var(--brand-hue) 20% 92%);
  --surface4-light: hsl(var(--brand-hue) 20% 85%);
  --surface-shadow-light: var(--brand-hue) 10% calc(var(--brand-lightness) / 5);
  --shadow-strength-light: .02;
}
Zrzut ekranu pokazujący wszystkie jasne kolory
Sandbox na CodePen

Ciemny motyw

Większość marek nie zaczyna od ciemnego motywu. Jest on wariantem ich głównego motywu, który jest zwykle jaśniejszy. Z kolei użytkownicy często wybierają ciemny motyw w różnych kontekstach, np. w nocy. Z tych powodów w przypadku ciemnych motywów należy pamiętać o 2 rzeczach:

  1. Użytkownicy będą korzystać z tego motywu w ciemności, więc przetestuj go w ciemności.
  2. Kolory powinny być stonowane, aby nie wibrowały na ekranie z powodu zbyt intensywnego koloru.

podgląd końcowego wyniku ciemnego motywu

Marka

Jasna tematyka używa 3 wartości kanałów kolorów sRGB marki bez zmian, ciemna tematyka nie używa. Nasycenie jest zmniejszone o połowę, a jasność o 50%.

* {
  --brand-dark: hsl(
    var(--brand-hue)
    calc(var(--brand-saturation) / 2)
    calc(var(--brand-lightness) / 1.5)
  );
}

Kolory tekstu

W ciemnym motywie kolory tekstu powinny być jasne. Te kolory mają wysokie wartości jasności, co powoduje, że są one bliższe bieli.

* {
  --text1-dark: hsl(var(--brand-hue) 15% 85%);
  --text2-dark: hsl(var(--brand-hue) 5% 65%);
}

Kolory powierzchni

W ciemnym motywie kolory powierzchni powinny być ciemne. Te kolory mają niską jasność i nasycenie, przy czym pierwsza powierzchnia jest najciemniejsza (10%).

* {
  --surface1-dark: hsl(var(--brand-hue) 10% 10%);
  --surface2-dark: hsl(var(--brand-hue) 10% 15%);
  --surface3-dark: hsl(var(--brand-hue) 5%  20%);
  --surface4-dark: hsl(var(--brand-hue) 5% 25%);
}

Cienie

W ciemnym motywie cienie mogą być bardzo trudne do zauważenia. Ma sens, bo ciężko jest zaciemnić coś, co jest już dość ciemne. Parametr --shadow-strength-dark jest tu bardzo przydatny, ponieważ pozwala przyciemnić cienie za pomocą jednej zmiennej.

* {
  --surface-shadow-dark: var(--brand-hue) 50% 3%;
  --shadow-strength-dark: .8;
}

Zwróć też uwagę na nasycenie cienia. Czy widzisz kolory, gdy patrzysz na interfejs? Spróbuj usunąć nasycenie z narzędzi deweloperskich. Co wolisz?

Wszystkie ciemne kolory

* {
  --brand-dark: hsl(var(--brand-hue) calc(var(--brand-saturation) / 2) calc(var(--brand-lightness) / 1.5));
  --text1-dark: hsl(var(--brand-hue) 15% 85%);
  --text2-dark: hsl(var(--brand-hue) 5% 65%);
  --surface1-dark: hsl(var(--brand-hue) 10% 10%);
  --surface2-dark: hsl(var(--brand-hue) 10% 15%);
  --surface3-dark: hsl(var(--brand-hue) 5%  20%);
  --surface4-dark: hsl(var(--brand-hue) 5% 25%);
  --surface-shadow-dark: var(--brand-hue) 50% 3%;
  --shadow-strength-dark: .8;
}
Zrzut ekranu pokazujący wszystkie ciemne kolory
Sandbox na CodePen

Ciemny motyw

Schemat kolorów polega na koordynowaniu jasności i nasycenia. Należy zadbać o wystarczającą nasycenie, aby kolor był widoczny, ale też o ledwie akceptowalne wyniki testów kontrastu, ponieważ obraz ma być przyciemniony i mieć niski kontrast.

podgląd wyników końcowych z ciemnego motywu;

Marka

* {
  --brand-dim: hsl(
    var(--brand-hue)
    calc(var(--brand-saturation) / 1.25)
    calc(var(--brand-lightness) / 1.25)
  );
}

Kolory tekstu

* {
  --text1-dim: hsl(var(--brand-hue) 15% 75%);
  --text2-dim: hsl(var(--brand-hue) 10% 61%);
}

Kolory powierzchni

* {
  --surface1-dim: hsl(var(--brand-hue) 10% 20%);
  --surface2-dim: hsl(var(--brand-hue) 10% 25%);
  --surface3-dim: hsl(var(--brand-hue) 5%  30%);
  --surface4-dim: hsl(var(--brand-hue) 5% 35%);
}

Cienie

* {
  --surface-shadow-dim: var(--brand-hue) 30% 13%;
  --shadow-strength-dim: .2;
}

Przyciemnij wszystkie kolory

* {
  --brand-dim: hsl(var(--brand-hue) calc(var(--brand-saturation) / 1.25) calc(var(--brand-lightness) / 1.25));
  --text1-dim: hsl(var(--brand-hue) 15% 75%);
  --text2-dim: hsl(var(--brand-hue) 10% 61%);
  --surface1-dim: hsl(var(--brand-hue) 10% 20%);
  --surface2-dim: hsl(var(--brand-hue) 10% 25%);
  --surface3-dim: hsl(var(--brand-hue) 5%  30%);
  --surface4-dim: hsl(var(--brand-hue) 5% 35%);
  --surface-shadow-dim: var(--brand-hue) 30% 13%;
  --shadow-strength-dim: .2;
}
Zrzut ekranu pokazujący przyciemnione kolory
Sandbox na CodePen

Dostępne kolory

Zwróć uwagę, że najciemniejszy kolor w zestawie kolorów tekstu ciemnego ma jasność 65%, a najjaśniejszy kolor na ciemnych powierzchniach – 25%. To 40% jasności oddziela je od siebie. W jasnym motywie jest 55% wolnego miejsca. Utrzymywanie różnic jasności między tekstem a kolorami powierzchni na poziomie około 40–50% może pomóc w zachowaniu wysokich współczynników kontrastu kolorów, a także stanowić subtelny element do regulacji w przypadku niskich wyników.

Nazywamy to „bump bump til ya Pass”, czyli interakcją polegającą na przesuwaniu poziomu jasności, aż narzędzie pokaże, że już mijam.

Naciśnij Shift + strzałka w dół, aby zmniejszyć jasność i zwiększyć kontrast, aż do uzyskania pożądanego efektu.

Każdy motyw utworzony w tym wyzwaniu uzyskuje punkty kontrastu. Schemat stonowanych kolorów ma najmniejszy kontrast, ale nadal spełnia minimalne wymagania. Aby ułatwić innym członkom zespołu korzystanie z dobrze kontrastujących kolorów, warto utworzyć nazwę klasy, która łączy kolor powierzchni z dostępnym kolorem tekstu.

.surface1 {
  background-color: var(--surface1);
  color: var(--text2);
}

.surface2 {
  background-color: var(--surface2);
  color: var(--text2);
}

.surface3 {
  background-color: var(--surface3);
  color: var(--text1);
}

.surface4 {
  background-color: var(--surface4);
  color: var(--text1);
}
Zrzut ekranu pokazujący łączenie ciemnej powierzchni z tekstem
Zrzut ekranu przedstawiający zaciemnioną powierzchnię i parowanie tekstu z VisBug

Rad Shadow

Motywy korzystają z klasy pomocniczej o nazwie .rad-shadow. Ten cień został wygenerowany za pomocą narzędzia Gładki cień, które bardzo sobie cenię. Pobrałem wygenerowany fragment kodu i dostosowałem go za pomocą własnych kolorów i obliczeń przezroczystości. Celem było stworzenie cienia, który można dostosować w ramach każdego schematu kolorów.

każda z nich obok siebie

Aby to osiągnąć, dla każdego schematu kolorów utworzyłem 2 zmienne: kolor cienia i natężenie cienia. Kolor służy do regulacji nasycenia i ciemności, a siła do łatwego zwiększania intensywności cieni w przypadku ciemnego schematu kolorów. Otrzymany wynik wyglądał tak.

:root {
  --surface-shadow-light: var(--brand-hue) 10% 20%;
  --shadow-strength-light: .02;
}

.rad-shadow {
  box-shadow:
    0 2.8px 2.2px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
    0 6.7px 5.3px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .01)),
    0 12.5px 10px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
    0 22.3px 17.9px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
    0 41.8px 33.4px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
    0 100px 80px hsl(var(--surface-shadow) / var(--shadow-strength))
  ;
}

Jeśli chciałbym pójść dalej z cieniem w swojej palecie kolorów, uczynię kąty cienia stałym elementem projektu, ponieważ kierunek światła powinien być taki sam dla wszystkich cieni w projekcie.

Korzystanie ze schematów kolorów

Po zdefiniowaniu kolorów należy je przekształcić w właściwości niezależne od schematu. Chodzi o to, że jako autor projektu schematu kolorów w kodzie CSS rzadko trzeba mieć dostęp do wartości konkretnego schematu kolorów. Chcę ułatwić Ci pozostawanie w ramach motywu.

Aby to osiągnąć, schemat kolorów powinien być używany wyłącznie za pomocą ogólnych właściwości niestandardowych, które zdefiniujemy za chwilę. Dzięki temu osoby korzystające z ustawień projektu nie muszą się martwić o to, jaki schemat kolorów jest obecnie ustawiony. Wystarczy, że użyją kolorów powierzchni i tekstu. Zamiast color: var(--text1-light) używaj color: var(--text1). Wszystkie adaptacje i obracanie kolorów są wykonywane na dużo wyższym poziomie w CSS.

W tym bloku kodu style łączące jasny motyw łączą ogólną właściwość niestandardową z kolorami określonymi w jasnym motywie. Teraz wszystkie użycia var(--brand) będą używać jasnego koloru marki.

Jasny motyw (automatyczny)

:root {
  color-scheme: light;
  --brand: var(--brand-light);
  --text1: var(--text1-light);
  --text2: var(--text2-light);
  --surface1: var(--surface1-light);
  --surface2: var(--surface2-light);
  --surface3: var(--surface3-light);
  --surface4: var(--surface4-light);
  --surface-shadow: var(--surface-shadow-light);
  --shadow-strength: var(--shadow-strength-light);
}

Witryna używa teraz jasnego motywu. To bardzo przyjemny moment. Zobaczmy jeszcze kilka przykładów użycia naszych zdefiniowanych wstępnie kolorów w innych kontekstach schematu kolorów.

Ciemny motyw (automatyczny)

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;

    --brand: var(--brand-dark);
    --text1: var(--text1-dark);
    --text2: var(--text2-dark);
    --surface1: var(--surface1-dark);
    --surface2: var(--surface2-dark);
    --surface3: var(--surface3-dark);
    --surface4: var(--surface4-dark);
    --surface-shadow: var(--surface-shadow-dark);
    --shadow-strength: var(--shadow-strength-dark);
  }
}

Jasny motyw

[color-scheme="light"] {
  color-scheme: light;

  --brand: var(--brand-light);
  --text1: var(--text1-light);
  --text2: var(--text2-light);
  --surface1: var(--surface1-light);
  --surface2: var(--surface2-light);
  --surface3: var(--surface3-light);
  --surface4: var(--surface4-light);
  --surface-shadow: var(--surface-shadow-light);
  --shadow-strength: var(--shadow-strength-light);
}

Ciemny motyw

[color-scheme="dark"] {
  color-scheme: dark;

  --brand: var(--brand-dark);
  --text1: var(--text1-dark);
  --text2: var(--text2-dark);
  --surface1: var(--surface1-dark);
  --surface2: var(--surface2-dark);
  --surface3: var(--surface3-dark);
  --surface4: var(--surface4-dark);
  --surface-shadow: var(--surface-shadow-dark);
  --shadow-strength: var(--shadow-strength-dark);
}

Motyw przyciemniony

[color-scheme="dim"] {
  color-scheme: dark;

  --brand: var(--brand-dim);
  --text1: var(--text1-dim);
  --text2: var(--text2-dim);
  --surface1: var(--surface1-dim);
  --surface2: var(--surface2-dim);
  --surface3: var(--surface3-dim);
  --surface4: var(--surface4-dim);
  --surface-shadow: var(--surface-shadow-dim);
  --shadow-strength: var(--shadow-strength-dim);
}

W tej chwili autorzy mogą dowolnie korzystać z dostępnych schematów kolorów ogólnych i nie muszą się już martwić o motywy.

Podsumowanie

Teraz, gdy już wiesz, jak to zrobić, jak Ty to zrobisz? 🙂

Stosujmy różne podejścia i poznajmy sposoby budowania obecności w internecie. Utwórz Codepen lub opublikuj własne demo, tweetuj je, a ja dodam je do sekcji Remixe społeczności poniżej.

Źródło

Remiksy utworzone przez społeczność – @chris-kruining dodał suwak barwy, kolory stanu i tryby kontrastu w przypadku kanałów no-preference, more i less: demonstracja.