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ą.
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
.
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;
}
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:
- Użytkownicy będą korzystać z tego motywu w ciemności, więc przetestuj go w ciemności.
- Kolory powinny być stonowane, aby nie wibrowały na ekranie z powodu zbyt intensywnego koloru.
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;
}
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.
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;
}
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.
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);
}
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.
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.