Tworzenie schematu kolorów

Podstawowe informacje o tym, jak utworzyć dynamiczny i konfigurowalny schemat kolorów

W tym poście chcę podzielić się przemyśleniami na temat sposobów zarządzania wieloma schematami kolorów w CSS. Wypróbuj wersję demonstracyjną

Wersja demonstracyjna

Jeśli wolisz film, obejrzyj tę wersję posta w YouTube:

Przegląd

Stworzymy dostępny system kolorów z właściwościami niestandardowymi i funkcją calc(), aby utworzyć stronę internetową, która dostosowuje się do preferencji użytkownika, a jednocześnie zapewnia minimalne wymagania dotyczące tworzenia. Zaczynamy od podstawowego koloru marki i tworzymy na jego podstawie system wariantów: 2 kolory tekstu, 4 kolory powierzchni i pasujący cień.

Ten przewodnik zaczyna się od zdefiniowania wszystkich kolorów w każdej palecie kolorów. Dopiero na samym końcu są one używane do zmiany strony.

Marka

Często kolor marki jest już ustalony i podany w formacie szesnastkowym lub RGB. Ten test interfejsu ma podstawowy kolor marki #0af. Najpierw w tym systemie kolorów wartość szesnastkową należy przekonwertować na hsl.

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

Aby umożliwić przyciemnianie lub rozjaśnianie koloru marki, np. o 20%, 3 kanały wartości koloru hsl muszą zostać wyodrębnione do własnych właściwości niestandardowych, np. w ten sposób:

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

CSS może wykonywać obliczenia na tych właściwościach koloru, np. calc(var(--brand-lightness) - 20%), aby zmniejszyć wartość jasności o 20%. Jest to podstawa tworzenia schematu kolorów, ponieważ CSS może utrzymywać wszystkie kolory w tej samej rodzinie odcieni, dostosowując nasycenie i jasność w przestrzeni barw HSL.

Jasny motyw

Każda wersja kolorystyczna będzie oznaczona odpowiednim schematem. W tym przypadku do każdej z nich zostanie dodany symbol -light.

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

Marka

Zaczynając od koloru marki, jest on przebudowywany przez umieszczenie 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 podstawowe elementy schematu kolorów wymagają kolorów tekstu. W jasnym motywie tekst powinien być bardzo ciemny. Zwróć uwagę, że jasność poniższych kolorów jest niska, znacznie poniżej 50%.

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

--text1-light, ponieważ przy jasności 10% jest bardzo ciemny, zachowuje wysoką saturację 100%, dzięki czemu kolor marki może nadal przebijać się przez ciemny granatowy.

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

Kolory powierzchni

Kolory powierzchni to tła, obramowania i inne dekoracyjne powierzchnie, na których lub w których znajduje się tekst. W jasnym motywie są to jasne kolory, w przeciwieństwie do ciemnych kolorów tekstu. Aby utworzyć jasne kolory za pomocą modelu HSL, użyjemy wyższych wartości procentowych w trzeciej wartości jasności. Zmniejszymy też nasycenie, aby jasne odcienie szarości nie wyglądały na zbyt 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%);
}

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

Cienie

Cienie w schemacie kolorów są dodatkowym atutem, ale nadają efektowi realistyczny charakter i pomagają mu wyróżnić się na tle nierealistycznych cieni opartych na czerni. W tym celu kolor cienia będzie korzystać z właściwości niestandardowej barwy, będzie lekko nasycony barwą, ale nadal bardzo ciemny. W zasadzie tworzy bardzo ciemny, lekko niebieski cień.

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

--surface-shadow-light nie jest zawarty w funkcji hsl. Dzieje się tak, ponieważ wartość--shadow-strength zostanie połączona w celu utworzenia pewnej nieprzezroczystości, a CSS potrzebuje tych elementów do przeprowadzenia obliczeń. Więcej informacji znajdziesz w sekcji cienia radialnego.

Jasne kolory razem

Nie musisz szukać informacji o tym, jak powstają poszczególne jasne kolory, ponieważ wszystkie są w jednym miejscu w 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 przedstawiający wszystkie jasne kolory,
Piaskownica w CodePen

Ciemny motyw

Większość marek nie zaczyna od ciemnego motywu. Jest to wariant ich głównego, zwykle jaśniejszego motywu. Użytkownicy często wybierają ciemny motyw w różnych sytuacjach, np. w nocy. Z tego powodu w przypadku motywów ciemnych pamiętam o 2 rzeczach:

  1. Użytkownicy będą zwykle korzystać z tego motywu w ciemności, więc testuj go w ciemności.
  2. Kolory powinny być mniej nasycone, aby nie wibrowały na ekranie z powodu zbyt dużej intensywności.

podgląd końcowego efektu ciemnego motywu,

Marka

W przypadku jasnego motywu używane są 3 wartości kanałów kolorów HSL marki bez zmian, a w przypadku ciemnego motywu nie. Nasycenie jest zmniejszone o połowę, a jasność o 50% w stosunku do wartości początkowej.

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

Kolory tekstu

W przypadku motywu ciemnego kolory tekstu powinny być jasne. Poniższe kolory mają wysokie wartości jasności, co sprawia, że są bliższe bieli.

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

Kolory powierzchni

W przypadku motywu ciemnego kolory powierzchni powinny być ciemne. Poniższe kolory mają niską jasność i nasycenie, a 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 to sens, ponieważ trudno przyciemnić coś, co jest już dość ciemne. W takiej sytuacji bardzo przydaje się funkcja --shadow-strength-dark, która pozwala przyciemnić cienie poprzez zmianę jednej zmiennej.

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

Sprawdź też, jak bardzo nasycony jest ten cień. Czy widzisz kolor, gdy patrzysz na interfejs? Spróbuj usunąć nasycenie w narzędziach deweloperskich. Która wersja bardziej Ci się podoba?

Ciemne kolory razem

* {
  --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 przedstawiający wszystkie ciemne kolory razem,
Piaskownica w CodePen

Przyciemniony motyw

Ten schemat kolorów opiera się na połączeniu jasności i nasycenia. Nasycenie powinno być wystarczające, aby odcień był widoczny, ale powinno też ledwo przekraczać wartości kontrastu, ponieważ ma być przyciemnione i o niskim kontraście.

podgląd końcowych wyników w przypadku przyciemnionego 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;
}

Przyciemnianie wszystkich kolorów

* {
  --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 przedstawiający wszystkie przyciemnione kolory,
Piaskownica w CodePen

Kolory z ułatwieniami dostępu

Zwróć uwagę, że najniższa jasność w przypadku ciemnego zestawu kolorów tekstu wynosi 65%, a najwyższa jasność w przypadku ciemnych powierzchni – 25%. To 40% różnicy w jasności. W jasnym motywie jest 55% wolnej przestrzeni. Utrzymywanie różnic w jasności między tekstem a kolorami powierzchni na poziomie około 40–50% może pomóc w utrzymaniu wysokich współczynników kontrastu kolorów, a jednocześnie stanowić subtelny sposób na dostosowanie w przypadku niskich wyników.

Nazywam to „bump bump til ya pass”, czyli zwiększanie wartości jasności, dopóki narzędzie nie pokaże, że spełniam wymagania.

naciśnięcie klawiszy Shift + strzałka w dół powoduje obniżenie jasności i zwiększenie kontrastu aż do przekroczenia

Każdy z motywów utworzonych w ramach tego wyzwania spełnia wymagania dotyczące kontrastu. Ciemna kompozycja kolorów ma najniższy kontrast, ale nadal spełnia minimalne wymagania. Aby pomóc innym członkom zespołu w używaniu kolorów o dobrym 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 przedstawiający przyciemnioną powierzchnię i pary tekstu
Zrzut ekranu z przyciemnioną powierzchnią i parą tekstu z VisBug

Rad Shadow

Motywy korzystają z klasy narzędziowej o nazwie .rad-shadow. Ten cień został wygenerowany w narzędziu Smooth Shadow, co bardzo doceniam. Wygenerowany fragment kodu dostosowałem do własnych kolorów i obliczeń krycia. Chodziło o utworzenie cienia, który można dostosować w ramach każdego schematu kolorów.

każdy cień obok siebie,

W tym celu utworzyłem 2 zmienne dla każdego schematu kolorów, które można dostosować: kolor cienia i siłę cienia. Kolor służy do dostosowywania nasycenia i ciemności, a siła to łatwy sposób na zwiększenie intensywności cienia w przypadku ciemnego schematu kolorów. Wynik końcowy wyglądał mniej więcej 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 w schemacie kolorów miałbym używać cieni, kąty cieni również byłyby stałą w tokenie projektu, ponieważ kierunek światła powinien być taki sam we wszystkich cieniach w projekcie.

Korzystanie ze schematów kolorów

Po wstępnym zdefiniowaniu kolorów czas przekształcić je we właściwości niezależne od schematu. Chodzi mi o to, że jako autor CSS w tym projekcie schematu kolorów rzadko trzeba mieć dostęp do wartości konkretnego schematu kolorów. Chcę, aby łatwo było zachować spójność z motywem.

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ć, który 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). Całe dostosowywanie i przekształcanie kolorów odbywa się na znacznie wyższym poziomie w CSS.

W przypadku motywu jasnego style połączeń w bloku kodu poniżej łączą ogólną właściwość niestandardową z kolorem charakterystycznym dla motywu jasnego. Teraz wszystkie użycia var(--brand) będą korzystać z 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 radosny moment! Zobaczmy jeszcze kilka takich momentów, gdy będziemy używać predefiniowanych 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);
}

Przyciemniony motyw

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

Na tym etapie autorzy mogą swobodnie używać podanych rodzajów schematów kolorów i nie muszą się już martwić o motywy.

Podsumowanie

Teraz, gdy wiesz, jak to zrobiłem, jak Ty byś to zrobił? 🙂

Urozmaićmy nasze podejście i poznajmy wszystkie sposoby tworzenia treści w internecie. Utwórz Codepen lub hostuj własną wersję demonstracyjną, wyślij mi ją w tweecie, a ja dodam ją do sekcji Remixy społeczności poniżej.

Źródło

Remiksy społecznościowe:@chris-kruining dodał suwak odcieni, kolory stanu i tryby kontrastu dla no-preference, moreless: demo.