Silnik, na którym stoi ta strona, obsługuje pięć serwisów. Cztery z nich wyglądają jak książka: papier, antykwa, akapity justowane, inicjał na początku tekstu. Piąty — ten — wygląda jak strona techniczna. Ten sam kod, ta sama wersja, jedno pole różnicy w konfiguracji.
theme: "dev",Poniżej opisuję, co się za tym polem kryje, bo droga do niego prowadziła przez trzy pomyłki, a każda z nich uczy czegoś innego.
Pomyłka pierwsza: skórka jako arkusz
Pierwszym odruchem było napisanie drugiego arkusza stylów i podmienianie go w zależności od instancji. Odruch jest zły z powodu, który widać dopiero przy trzeciej zmianie: dwa arkusze trzeba utrzymywać równolegle. Poprawka koloru linii w jednym miejscu nie dociera do drugiego i po miesiącu serwisy różnią się rzeczami, o których nikt nie decydował.
Skórka nie jest zbiorem reguł. Jest zbiorem WARTOŚCI, które reguły odczytują. Komponenty w ogóle nie wiedzą, że istnieje coś takiego jak motyw — biorą tokeny.
[data-theme="dev"] {
--paper: oklch(0.16 0.008 250);
--ink: oklch(0.95 0.003 250);
--ink-soft: oklch(0.78 0.006 250);
--rule: oklch(0.32 0.008 250);
--prose-size: 1.05rem;
}Atrybut siedzi na elemencie html i bierze się wprost z konfiguracji instancji. Instancja, która nie deklaruje niczego, dostaje skórkę książkową — czyli dokładnie to, co miała przed dodaniem tej funkcji. To warunek, nie uprzejmość: cztery działające serwisy nie mogą zauważyć, że pod nimi coś się zmieniło.
Pomyłka druga: zmienna, której nikt nie czyta
Najciekawsza z całej trójki. Chciałem, żeby skórka techniczna używała kroju bezszeryfowego wszędzie tam, gdzie książkowa używa antykwy. Wydawało się to jednolinijkowe: wystarczy w selektorze skórki nadpisać zmienną kroju szeryfowego stosem bezszeryfowym i wszystkie komponenty pójdą za nią.
Nie poszły. Tytuł wpisu został szeryfowy, mimo że reguła była poprawna i widoczna w narzędziach przeglądarki.
Przyczyna leży w tym, jak Tailwind traktuje dyrektywę `@theme inline`. Wartość zmiennej wkleja się wtedy wprost do wygenerowanych klas narzędziowych zamiast zostać odwołaniem. Klasa `font-serif` nie mówi „użyj wartości zmiennej”, tylko od razu zawiera nazwę kroju. Nadpisanie zmiennej nie ma czego zmienić.
[data-theme="dev"] .font-serif,
[data-theme="dev"] .prose-literary,
[data-theme="dev"] h1,
[data-theme="dev"] h2,
[data-theme="dev"] h3 {
font-family: var(--font-sans);
}Wniosek szerszy niż sam Tailwind: warstwa, która optymalizuje przez wklejanie wartości, przestaje być warstwą pośrednią. Wszystko, co na niej budujesz w czasie wykonania, przestaje działać — i dowiadujesz się o tym ze zrzutu ekranu, nie z komunikatu błędu.
Pomyłka trzecia: reguła, która sięga za daleko
Ciemny nagłówek wymagał rozjaśnienia ikon, bo malują się kolorem tuszu i na czarnym tle znikały. Dopisaliśmy regułę ustawiającą kolor na nagłówku i stopce, a do tego wyjątek dla treści strony, żeby przypadkiem nie objąć jej tym samym.
Wyjątek okazał się gorszy od problemu. Selektor złożony z atrybutu i nazwy elementu ma wyższą swoistość niż pojedyncza klasa narzędziowa, więc kolor tekstu na przycisku w treści przestał działać. Efekt: dwa przyciski na stronie głównej miały niewidoczne napisy i widać było tylko ten trzeci, który kolor miał wpisany w atrybucie stylu.
Reguła obramowania nie ma prawa sięgać poza obramowanie. Zamiast wyjątku — zawężenie zakresu, i problem znika razem z wyjątkiem.
Co nie należy do skórki
Ostatnia rzecz jest projektowa, nie techniczna. Nie wszystko, co ma kolor, powinno być tokenem.
W blokach konsoli czerń powłoki uniksowej i granat PowerShella są wpisane na sztywno. To nie jest niedopatrzenie: te dwa kolory są cytatem z rzeczywistości. Czytelnik rozpoznaje po nich system, zanim przeczyta pierwszą linię, a instancja nie ma prawa tego przedefiniować, bo nie ona o tym decyduje.
Odwrotny przykład: kolor akcentu. W skórce książkowej była to ciemna zieleń i nadawała się na tło całego pasa nagłówka. Po przejściu na ciemną skórkę ten sam token musiał się rozjaśnić do miętowego — i pas z nagłówkiem CV zamienił się w świecący kloc na pół ekranu.
Nauka nie brzmi „dobierz inny odcień”. Brzmi: akcent ma być akcentem — kreską, etykietą, jednym przyciskiem. Kolor, który raz jest powierzchnią, a raz sygnałem, prędzej czy później zawiedzie w jednym z tych zastosowań.
Bilans
Skórka techniczna to około stu linii CSS, jedno pole w typie konfiguracji i trzy miejsca w komponentach, gdzie sprawdzane jest, która jest aktywna. Cztery pozostałe instancje nie zauważyły niczego — sprawdzone po wdrożeniu, na żywo, na każdej z nich.
To jest cała miara sukcesu przy takiej zmianie. Nie to, że nowy wariant wygląda dobrze, tylko że stare wyglądają dokładnie tak jak wczoraj.