Tworzenie schematu kolorów

Podstawowe informacje o tworzeniu dynamicznego i konfigurowalnego schematu kolorów

W tym poście przedstawię sposoby zarządzania różnymi schematami kolorów w CSS. Wypróbuj wersję demonstracyjną

Demonstracja

Jeśli wolisz film, oto wersja tego posta na YouTube:

Przegląd

Stworzymy łatwo dostępny system kolorów z właściwościami niestandardowymi i elementem calc(), który pozwoli utworzyć stronę internetową, która będzie dostosowywać się do preferencji użytkowników, a jej tworzenie powinno być ograniczone do minimum. Zaczynamy od podstawowego koloru marki, a potem tworzymy na jego podstawie system jego odmian: 2 kolory tekstu, 4 kolory powierzchni i pasujący cień.

Przewodnik rozpoczyna się od zdefiniowania wszystkich kolorów dla każdego schematu kolorów. Są one używane do zmiany strony dopiero na samym końcu.

Marka

Często kolor marki jest już określony i jest dostarczany w formacie szesnastkowym lub rgb. To wyzwanie GUI ma podstawowy kolor marki: #0af. Najpierw w przypadku tego systemu kolorów wartość szesnastkowa musi zostać przekonwertowana na hsl.

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

Aby wprowadzić przyciemnienie lub rozjaśnienie koloru marki, np. 20%, 3 kanały wartości koloru hsl trzeba wyodrębnić do własnych właściwości niestandardowych, na przykład:

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

CSS może wykonać obliczenia na tych właściwościach koloru, 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 utrzymać tę samą rodzinę odcieni dzięki dostosowaniu poziomu nasycenia i jasności hsl.

Jasny motyw

Każda wersja koloru zostanie oznaczona zgodnie ze swoim schematem dopasowania. W tym przypadku każda wersja ma atrybut -light.

podgląd wyników zakończenia jasnego motywu

Marka

Aby dodać kolor marki, należy dodać właściwości niestandardowe --brand-hue, --brand-saturation i --brand-lightness w nawiasie funkcji hsl () bez żadnych obliczeń:

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

Kolory tekstu

Podstawowym elementem schematu kolorów są kolory tekstu. W jasnym motywie tekst powinien być bardzo ciemny. Zwróć uwagę, że jasność tych kolorów jest niska, czyli poniżej 50%.

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

--text1-light jest bardzo ciemny przy 10% jasności, więc utrzymuje 100% pełnego nasycenia, aby kolor marki nadal mógł zajrzeć do ciemnogranatowego granatu.

--text2-light, nie jest tak ciemny, jak pierwszy. Kolor, który jest lepszy i drugorzędny. Jest też znacznie mniej nasycony.

Kolory powierzchni

Kolory powierzchni to tła, ramki i inne ozdobne powierzchnie, na których tekst jest ułożony. W przypadku jasnego motywu są to jasne kolory, w przeciwieństwie do kolorów tekstu, które były ciemne. Aby utworzyć jasne kolory z hsl, w trzeciej wartości jasności użyjemy wyższych wartości procentowych. Obniżymy też nasycenie, aby jasnoszary nie wyglądały na zbyt przebarwione.

* {
  --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, aby uzyskać elementy interaktywne, takie jak :focus czy :hover, lub aby upodobnić je do warstw papieru. W takich przypadkach dobrze jest zmienić kolor --surface2-light po najechaniu na --surface3-light, ponieważ najechanie kursorem spowoduje zwiększenie kontrastu (jasność od 99% do 92% – przyciemnienie).

Cienie

Cienie w schemacie kolorów są przesadzone, ale dodają efektu realistycznego charakteru i wyróżniają się na tle nierealistycznych cieni opartych na czerni. W tym celu kolor cienia będzie miał swoją niestandardową właściwość – będzie nieco nasycony, ale wciąż bardzo ciemny. Tworząc bardzo ciemny, lekkoniebieski cień.

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

Funkcja --surface-shadow-light nie jest zawarta w funkcji hsl. Dzieje się tak, ponieważ wartość --shadow-strength zostanie połączona w celu uzyskania pewnej przezroczystości, a CSS potrzebuje fragmentów w celu wykonania obliczeń. Więcej informacji znajdziesz w sekcji „rad shadow”.

Jasne kolory

Nie musisz szukać jasnych kolorów, bo 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 kolory świateł
Piaskownica w CodePen

Ciemny motyw

Większość marek nie zaczyna od ciemnego motywu, ale jest to wariant głównego motywu, zwykle jaśniejszy. Z drugiej strony użytkownicy często wybierają ciemny motyw do różnych kontekstów, np. w nocy. Dlatego właśnie muszę zwrócić uwagę na 2 rzeczy:

  1. Użytkownicy zwykle są w ciemności, gdy używają tego motywu, więc przeprowadzaj testy w ciemności.
  2. Kolory powinny się zmniejszyć, by ekran nie wibrował, bo jest zbyt intensywny.

podgląd wyniku końcowego ciemnego motywu

Marka

W jasnym motywie wykorzystano 3 wartości kanałów koloru hsl marki bez żadnych zmian, a ciemny motyw nie. Nasycenie jest zmniejszone o połowę, a jasność zmniejszona o względnie 50%.

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

Kolory tekstu

W przypadku ciemnego motywu kolory tekstu powinny być jasne. Poniższe kolory mają wysoką jasność, dlatego są bardziej zbliżone do bieli.

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

Kolory powierzchni

W przypadku ciemnego motywu kolory powierzchni powinny być ciemne. Poniższe kolory mają niską jasność i nasycenie. 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 trybie ciemnym cienie mogą być bardzo słabo widoczne. Ma to sens, bo trudno jest zaciemnić coś, co jest już dość ciemne. W tym przypadku bardzo przydatna jest funkcja --shadow-strength-dark, która pozwala nam ograniczać cienie poprzez zmianę jednej zmiennej.

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

Zwróć też uwagę na poziom nasycenia danego cienia. Czy widzisz kolor, gdy patrzysz na interfejs? Spróbuj usunąć z narzędzi deweloperskich nasycenie. Co wolisz?!

Całe 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 przedstawiający wszystkie ciemne kolory
Piaskownica w CodePen

Przyciemniony motyw

Ten schemat kolorów ma na celu dostosowanie jasności i nasycenia obrazu. Powinno ono być wystarczająco nasycone, aby barwa była nadal widoczna, ale jednocześnie nie powinna przekraczać wyników kontrastu, ponieważ i tak powinien być przyciemniony i ma niski kontrast.

podgląd wyników końcowych 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 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 przyciemnione kolory
Piaskownica w CodePen

Dostępne kolory

Zwróć uwagę, że najniższa jasność ciemnego zestawu kolorów tekstu wynosi 65%, a najmniejsza na ciemnych powierzchniach – 25%. To 40% przestrzeni między nimi. Tryb jasny zapewnia 55% oddychania. Utrzymanie różnic w jasności tekstu i powierzchni na poziomie około 40–50% może pomóc w utrzymaniu wysokiego współczynnika kontrastu kolorów, a jednocześnie pozwala subtelnie dostosować go w przypadku słabych wyników.

Nazywamy to „bump til ya pass”, czyli interakcją podniesienia wartości jasności do chwili, gdy narzędzie pokaże, że przechodzę.

Naciśnięto
Shift + strzałka w dół, aby zmniejszyć jasność i zwiększyć kontrast do zakończenia

Każdy z motywów utworzonych w ramach tego wyzwania kontrastuje ze sobą. Ciemny schemat kolorów ma najniższy kontrast, ale spełnia wymagania minimalne. Aby pomóc innym członkom zespołu użyć dobrze kontrastujących kolorów, warto utworzyć nazwę klasy, która łączy kolor powierzchni z łatwo 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 przyciemnioną powierzchnię i łączenie tekstu
Zrzut ekranu pokazujący przyciemnioną powierzchnię i parowanie tekstów z urządzeniem VisBug

Jasny cień

Motywy korzystają z klasy narzędziowej o nazwie .rad-shadow. Cień ten został wygenerowany w narzędziu Gładki cień, za co bardzo doceniam swoje zdanie. Wygenerowany fragment kodu został utworzony na podstawie własnych obliczeń kolorów i przezroczystości. Powodem było utworzenie cienia, który mogę dostosować w ramach każdego schematu kolorów.

cienie obok siebie

W tym celu utworzyliśmy 2 zmienne dla każdego schematu kolorów do dostosowania: kolor cienia i siłę cienia. Kolor służy do dostosowania nasycenia i ciemności, a siła pozwala łatwo zwiększyć intensywność cieni w przypadku ciemnego schematu kolorów. Wynik końcowy był podobny do tego.

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

Gdybym poszła dalej z cieniami w swoim schemacie kolorów, również ustawiłbym kąty cienia jako stałą tokena projektu, ponieważ kierunek światła powinien być taki sam we wszystkich cieniach projektu.

Korzystanie ze schematów kolorów

Po wstępnym definiowaniu kolorów nadszedł czas, aby przekształcić je w właściwości niezależne od schematu. Jako autor CSS w projekcie schematu kolorów rzadko trzeba mieć dostęp do wartości konkretnego schematu kolorów. Chcę, żeby było to łatwe do utrzymania w ramach motywu.

W tym celu schemat kolorów powinien być używany wyłącznie przez ogólne właściwości niestandardowe, które za chwilę zdefiniujemy. Dzięki temu osoby korzystające ze zmiennych projektowych nie muszą martwić się o obecnie ustawiony schemat kolorów, a tylko użyć koloru powierzchni i tekstu. Zamiast color: var(--text1-light) użyj color: var(--text1). Dostosowanie i przestawianie kolorów odbywa się znacznie częściej w CSS.

Omawiając style połączeń jasnego motywu w poniższym bloku kodu, połącz ogólną właściwość niestandardową z konkretnym kolorem jasnego. Teraz we wszystkich zastosowaniach var(--brand) będzie używany jasny kolor 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 fajny, udany moment. Pokażmy więcej takich scenariuszy, ponieważ wykorzystujemy gotowe kolory w innych kontekstach schematów 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ą używać podanych ogólnych schematów kolorów w razie potrzeby i nie muszą już się martwić o motywy.

Podsumowanie

Skoro już wiesz, jak to udało mi się osiągnąć, to jak? 🙂

Stwórzmy różne metody i nauczmy się wszystkiego, jak rozwijać się w internecie. Utwórz program Codepen lub udostępnij własną prezentację i prześlij mi go na tweeta, a dodam ją do sekcji remiksów ze społeczności poniżej.

Źródło

Remiksy społeczności – @chris-kruining dodał suwak odcieni, kolory stanu i tryby kontrastu dla no-preference, more i less: demonstracja.