Tworzenie schematu kolorów

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

W tym poście chcę podzielić się sposobami zarządzania wieloma schematami kolorów w kodzie 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 na jego podstawie tworzymy system 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 jest już ustalony i przesyłany jako hex 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 umożliwić przyciemnienie lub rozjaśnienie koloru marki, np. o 20%, 3 kanały wartości koloru hsl muszą zostać wyodrębnione w osobne właściwości niestandardowe, tak jak w tym przykładzie:

* {
  --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%. Jest to podstawa tworzenia schematu kolorów, ponieważ CSS może zachować wszystkie kolory w tej samej rodzinie odcieni, dostosowując nasycenie i jasność hsl.

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 jasnego motywu.

Marka

Zaczynając od koloru marki, został on odtworzony przez owinięcie właściwości niestandardowych --brand-hue, --brand-saturation i --brand-lightness w nawiasach funkcji hsl () bez żadnych obliczeń:

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

Kolory tekstu

Następnie musisz dobrać kolory tekstu. W 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 jasnym motywie 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. Zmniejszym też nasycenie, aby jasne szarości nie były zbyt przyciemnione.

* {
  --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%);
}

Utworzono 4 kolory powierzchni, ponieważ kolory dekoracyjne wymagają zwykle większej liczby wariantów, na przykład w przypadku interaktywnych momentów, takich jak :focus lub :hover, lub w celu stworzenia wyglądu warstw 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 ciemniejszy).

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. Aby to zrobić, kolor cienia będzie korzystać z właściwości niestandardowej odcień, będzie nieco nasycony, ale nadal bardzo ciemny. 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 przeprowadzić obliczenia. Aby dowiedzieć się więcej, przejdź do sekcji dotyczącej sekcji ciemnej.

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 to wariant 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ą używać tego motywu w ciemnych warunkach, więc przeprowadź testy 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

Jasny motyw używa 3 wartości kanałów kolorów sRGB marki bez zmian, ciemny motyw 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. To ma sens, ponieważ trudno jest przyciemnić coś, co jest już dość ciemne. W tym miejscu --shadow-strength-dark okazuje się bardzo przydatne, ponieważ pozwala przyciemnić cienie przez zmianę 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 w devtools.

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

Motyw przyciemniony

Ten schemat kolorów opiera się na jasności i nasycenie. Należy zadbać o wystarczającą nasycenie, aby zachować widoczność odcienia, ale jednocześnie nie przekraczać wartości kontrastu, ponieważ obraz ma być przyciemniony i mieć niski kontrast.

podgląd końcowych wyników motywu przyciemnionego;

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

przyciemniać 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 tekstu w ciemnym zestawie kolorów ma jasność 65%, a najjaśniejszy kolor ciemnych powierzchni – 25%. To 40% różnicy w jasności. W jasnym motywie jest 55% miejsca na oddech. Utrzymywanie różnic jasności między tekstem a kolorami powierzchni na poziomie około 40–50% może pomóc w zachowaniu wysokiego kontrastu kolorów, a także stanowić subtelny element do regulacji w przypadku niskich wyników.

Nazywam to „bump bump til ya pass”, czyli interakcja polegająca na zwiększaniu wartości jasności, aż narzędzie wskaże, że jestem na pasie.

Naciśnij Shift + strzałka w dół, aby zmniejszyć jasność i zwiększyć kontrast, aż do przejścia.

Wszystkie motywy utworzone w ramach tego wyzwania mają prawidłowe wartości kontrastu. Schemat stonowanych kolorów ma najmniejszy kontrast, ale nadal spełnia minimalne wymagania. Aby ułatwić innym członkom zespołu korzystanie z dobrych kolorów o wysokim kontraście, 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 z ciemnym tłem i tekstem w połączeniu 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ę. Użyłem wygenerowanego fragmentu kodu i dostosowałem go do własnych kolorów oraz obliczeń dotyczących krycia. 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 kodu CSS w ramach tego projektu kolorów rzadko będziesz potrzebować dostępu do wartości konkretnego projektu 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 tych zmiennych nie muszą się martwić o to, jaki schemat kolorów jest aktualnie 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? 🙂

Zróżnicujemy nasze podejścia i poznamy wszystkie sposoby tworzenia stron internetowych. Utwórz Codepen lub prześlij własne demo, tweetuj je, a ja dodam je do sekcji Remixe społeczności poniżej.

Źródło

Remixy społeczności – @chris-kruining dodał suwak odcienia, kolory stanu i tryby kontrastu dla no-preference, moreless: demo.