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ą.
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
.
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;
}
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 ciemnych warunkach, więc przeprowadź testy 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, 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;
}
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.
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 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.
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);
}
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.
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
, more
i less
: demo.