Podstawowy przegląd sposobu 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ą
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 na jego podstawie 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, na przykład 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
.
Marka
Zaczynając od koloru marki, odtworzyliśmy go, owijając właściwości niestandardowe --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, bo jest to kolor dodatkowy. Jest też 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, np. 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 ś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. 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 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 o promienistym cieniu.
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 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:
- Użytkownicy będą używać 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
Jasny motyw używa 3 wartości kanałów kolorów sRGB marki bez zmian. Motyw ciemny nie używa tych wartości. 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łaśnie w tym przypadku --shadow-strength-dark
jest 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;
}

Motyw przyciemniony
Ten schemat kolorów opiera się na jasności i nasycenie. Należy zastosować wystarczającą nasycenie, aby kolor był widoczny, ale jednocześnie nie przekraczać wartości kontrastu, ponieważ obraz ma być ciemny 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;
}
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;
}

Dostępne kolory
Zwróć uwagę, że najciemniejszy kolor tekstu to 65%, a najjaśniejszy kolor ciemnych powierzchni to 25%. To 40% różnicy w jasności pomiędzy nimi. 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 wysokiego współczynnika kontrastu kolorów, a także stanowić subtelny element do regulacji w przypadku niskich wyników.
Nazywam to „bump bump til ya pass”, co oznacza interakcję polegającą na zwiększaniu wartości jasności, aż narzędzie wskaże, że jestem na pasie.
Wszystkie motywy utworzone w ramach tego wyzwania spełniają kryteria 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);
}

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ń stopnia krycia. 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 tematu.
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 ze zmiennych projektu 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 dostosowania 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 zastosowania 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 zdefiniowanych 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
, more
i less
: demo.