Ваші документації виглядають «нормально», поки не з’явиться реальний користувач з реальними налаштуваннями: увімкнений темний режим, активована зменшена анімація, OLED-екран і рівень масштабування в браузері, який ви не тестували. Тоді блоки коду світяться, як зварювальна дуга, стани наведення в боковій панелі зникають, а плавна прокрутка продовжує бігти, ніби намагається виграти марафон.
Теми ламаються нудними способами: непослідовні кольори, нечитаемий контраст, стрибки верстки та «одноразовий» CSS, що перетворюється на звалище. Токени дизайну — реалізовані через CSS-змінні і розумну стратегію темного режиму та зменшеної анімації — допомагають зробити сайт документації нудним у продакшні. Нудне — це добре.
Що таке токени дизайну насправді (і чим вони не є)
Токен дизайну — це іменоване рішення. Не просто колір. Не шрифт. Не «#1d9bf0».
Рішення: «це акцентний колір» або «це колір кільця фокусу» або «це відстань між параграфами, що йдуть один за одним». Токени дозволяють говорити про рішення так, щоб вони пережили редизайн, темний режим і три різні CSS-фреймворки, які намагаються жити в одному репозиторії.
Шари токенів: не пропускайте це, інакше потім пошкодуєте
Якщо ви все сплющите в одну купу змінних, ви отримаєте тему, що не зможе еволюціонувати. Потрібні шари:
- Базові токени: сирі примітиви — кольори (по можливості в перцепційному просторі), сімейства шрифтів, кроки відступів.
- Семантичні токени: імена, основані на намірі, як-от
--color-bg,--color-fg,--color-accent. - Токени компонентів: лише за потреби, наприклад
--codeblock-bgабо--sidebar-hover-bg.
Базові токени можуть змінюватися під час ребрендингу. Семантичні токени повинні залишатися стабільними. Токени компонентів — це контрольований вихід — використовуйте їх обережно і лише коли семантичні токени не можуть виразити обмеження компонента.
Чим токени не є
- Не місце для викидання кожного випадкового hex-коду з макета.
- Не заміна примітивів верстки та розумного дизайну компонентів.
- Не привід вигадувати милі назви на кшталт
--blueberry-muffin. Ви не керуєте крамницею морозива.
Один надійний евристик: якщо ім’я змінної не допоможе комусь налагодити проблему з контрастом о 2:00 ночі, то це не токен — це секрет.
Факти та історичний контекст, що мають значення у 2025
Теми і токени відчуваються модними. Вони такими й є, але також вони є точкою злиття кількох десятиліть історії CSS, роботи з доступністю та платформних конвенцій. Ось конкретні факти, що впливають на сучасні теми документації:
- CSS custom properties (змінні) почали широко підтримуватися близько 2017 року. Достатньо старі, щоб їм довіряти в продакшні, але ще є команди, що уникають їх із звички.
prefers-color-schemeстав широко придатним у сучасних браузерах близько 2020–2021 років, перетворивши темний режим із «додаткового CSS-файла» на повноцінний сигнал користувацької переваги.prefers-reduced-motion— медіа-запит, що походить з налаштувань ОС для доступності; ігнорувати його — те саме, що ігнорувати «мені стає погано від руху». Користувачі це помічають.- Керівництво WCAG щодо контрасту (зокрема 2.1 і пізніші версії) відштовхнуло команди від «виглядає добре на моєму ноуті» до вимірюваної читабельності для нормального і великого тексту.
- Прийняття OLED зробило чисто чорні фони більш поширеними — але й надто яскравий текст і насичені акценти здаються різкішими. «Темний режим» — це не «#000 скрізь».
- Підсвітка синтаксису для блоків коду тепер — важлива зона читабельності. Це не декоративно; це фактично спосіб комунікації вашої документації. Погані токени тут мовчки навантажують користувачів.
- Зусилля зі стандартизації токенів дизайну (включно з форматами й інструментами спільноти) нормалізували ідею токенів як артефакту пайплайну, а не лише як CSS-змінних у файлі.
- Системні UI-конвенції привчали користувачів очікувати, що вибір теми зберігатиметься для сайту, але за замовчуванням слідуватиме системним налаштуванням. Якщо ви з цим боретесь, ви програєте. Тихо, але програєте.
Це не дрібниці. Саме тому підхід «просто оберіть кілька кольорів» вмирає, коли ваша документація стає популярною.
Модель токенів, що не розвалиться пізніше
Теми для документації мають особливу проблему: вони здебільшого про типографіку та щільність контенту, з невеликими інтерактивними елементами (навігація, пошук, кнопки копіювання коду). Це спонукає команди недодизайнити токени. Потім приходить перший «дрібний» запит на зміну — нові типи викликів уваги, бейджі методів API, інша тема підсвітки синтаксису — і раптом ви ловитеся на тому, чому #fff використовується 46 разів у 12 файлах.
Почніть з обмежень: документація — не маркетинговий сайт
Ваша тема документації повинна оптимізуватися для:
- Читабельності під час тривалих сесій.
- Послідовності між типами контенту (Markdown, таблиці, код, діаграми).
- Передбачуваної взаємодії (стани фокусу, наведення, навігація клавіатурою).
- Низького ризику регресій при зміні токенів.
Ваша тема не повинна оптимізуватися для:
- Максимального насичення бренду на кожному пікселі.
- Незвичних анімацій.
- «Задоволення», що ламає прокрутку або викликає симптоми чутливості до руху.
Опінійоване найменування токенів
Використовуйте схему найменування, яка кодує намір і масштаб. Наприклад:
--space-1,--space-2,--space-3… для кроків відступів (базові токени).--radius-1,--radius-2… для скруглень кутів.--color-neutral-0…--color-neutral-100для нейтральної шкали (базові токени).--color-bg,--color-fg,--color-muted,--color-border(семантичні токени).--color-link,--color-link-hover,--color-focus-ring(семантичні токени, все ще на рівні наміру).
Уникайте прив’язки семантичних токенів до назв брендів: --color-twitter-blue — це майбутній баг. Бренд зміниться або контекст зміниться, і ім’я токена буде брехати.
Кількість токенів: менше, ніж ви думаєте, більше, ніж хочете
Якщо ви визначите 300 токенів в перший день, ви не будуєте тему — ви собі створюєте другу роботу.
Якщо ви визначите 12 токенів, ви будуєте пастку.
Практична відправна точка для теми документації:
- Нейтральна шкала: 10–14 кроків.
- Акцент + стани: акцент, акцент-наведення, акцент-приглушений, кільце фокусу.
- Статусні кольори: успіх/попередження/помилка/інфо з двома кроками кожен (суцільний + фоновий).
- Типографіка: 2 сімейства шрифтів (ui + моно), 1–2 токени висоти рядка, кроки масштабу шрифтів.
- Відступи + радіуси: 6–8 кроків кожне.
Цього достатньо, щоб промоделювати тему всього сайту без того, щоб ваш CSS перетворився на інтерпретаторний танець.
CSS-змінні в продакшні: механіка та гострі кути
CSS custom properties — це змінні, що вирішуються під час виконання. Це і можливість, і підводний камінь. Вони наслідуються, їх можна перевизначати, і вони беруть участь у каскаді. Це робить їх ідеальними для тем.
Використовуйте каскад свідомо
Каскад — це не хаос. Це площина контролю. Ваш сайт документації має визначати токени у:
:rootдля значень за замовчуванням.[data-theme="dark"]для перевизначень темного режиму.- Опційно: області компонентів, як-от
.codeblock, тільки для токенів компонентів.
Не визначайте токени на випадкових вкладених рівнях, якщо ви не навмисно їх скопили. Інакше ви отримаєте баги виду «працює на одній сторінці», бо контейнер змінив токен, і дочірній компонент його наслідував.
Віддавайте перевагу семантичним токенам у стилізації компонентів
Компонент має посилатися переважно на семантичні токени. Приклад:
Блок коду має використовувати --color-bg-elevated і --color-fg, а не --color-neutral-95.
Якщо ви закріпите кроки базової шкали у компонентах, ви не зможете переналаштувати контраст без редагування CSS компонентів.
Продуктивність: змінні не ваш вузький місць, поки ним не стануть
Більшість тем не стикаються з проблемами продуктивності тільки через змінні. Але ви можете створити проблеми:
- Анімація змінної, що впливає на верстку або важкі для рендерингу властивості по всій сторінці.
- Надмірне використання
filter,backdrop-filterабо величезних box-shadow під час перемикання тем. - Тригери дорогих перерісовувань через перемикання теми на корені при кожній дрібній взаємодії.
Робіть перемикання тем рідкісними (дія користувача, не наведення). Тримайте переходи тонкими і обмеженими.
Цитата, яку варто пам’ятати
«Надія — не стратегія.» — Генерал Гордон Р. Салліван
Правильність теми — це не справа відчуттів. Вимірюйте контраст, тестуйте зменшену анімацію і запускайте регресійні перевірки.
Темний режим «як у X»: високий контраст, мінімум драми, не абсолютний чорний
Люди кажуть «темний режим як у X», бо він читабельний, чіткий і не виглядає як штурманська панель з наукової фантастики. Здебільшого він використовує майже чорний фон (не чистий чорний), трохи підняті поверхні і яскравий, але контрольований текст. Важлива річ — нейтральна шкала і те, як ви її розподіляєте по поверхнях.
Чому майже чорний краще за чистий чорний для документації
Чистий чорний (#000) максимізує контраст, що звучить добре, поки ви не читаєте 40 хвилин. Багато користувачів скаржаться на гало (світіння країв) від яскравого тексту на чистому чорному. Майже чорний зменшує блік, але все ще відчувається «темним».
Також: не всі дисплеї поводяться однаково. Деякі монітори стискають тіні, деякі телефони підвищують контраст, а деякі браузери по-іншому керують кольорами. Майже чорний дає простір для створення підйому поверхонь і меж без покладання на невидимі значення.
Визначте поверхні: базова, піднята, вбудована
Темам документації потрібні токени поверхонь. Якщо у вас є лише один фон, ви почнете вигадувати випадкові сірі. Використовуйте невеликий набір поверхонь:
--color-bgдля основи сторінки.--color-bg-elevatedдля навігації, панелей, карток.--color-bg-insetдля блоків коду, викликів уваги та вбудованих контейнерів.
Роби межі справжніми в темному режимі
У світлому режимі можна дозволити собі тонкі межі. У темному режимі межі або зникають, або стають неоновими контурними лініями. Токенізуйте межі за наміром:
--color-borderдля стандартних ліній.--color-border-strongдля роздільників і ліній таблиць.
Якщо ви використовуєте один колір для всіх меж, таблиці і бокові панелі зіллються в кашу, особливо для користувачів з низьким сприйняттям контрасту.
Посилання й акценти: режим «занадто синій»
Теми «як у X» використовують насичений акцент, але контролюють, де він з’являється. Ваші документи мають робити те саме:
- Посилання: колір акценту, але уникайте надто тонких підкреслень на темному фоні.
- Кнопки: фон акценту з читабельним текстом, але тримайте стани наведення в межах невеликого різницевого діапазону.
- Кільця фокусу: не переробляйте акцент механічно; підберіть колір кільця, що буде видно і на світлих, і на темних поверхнях.
Жарт №1: Темний режим — це не «зробити все чорним». Це не темізація; це відключення електроенергії для типографіки.
Підсвітка синтаксису: не дозволяйте їй паразитувати
Блоки коду — це місце, де більшість тем для темного режиму тихо провалюються. Фон темний, потім токени використовують надто насичені кольори, які мерехтять, і очі користувача йдуть у відпустку. Токенізуйте кольори синтаксису окремо і тримайте їх у контрольованій палітрі.
Практичне правило: тримайте кольори синтаксису менш насиченими, ніж акцент, і переконайтесь, що коментарі читабельні, але не домінують. Якщо колір коментаря занадто блідий, люди не розрізнятимуть код і анотацію; якщо занадто яскравий — він створює візуальний шум.
Зменшена анімація: контракт, який ви вже порушуєте
Зменшена анімація — це не «приємна опція». Це явна користувацька перевага. Коли користувач увімкнув зменшену анімацію, він повідомляє, що анімація може викликати дискомфорт або нудоту. Якщо ваш сайт документації все ще плавно прокручується, робить кросфейди, паралакс-прокрутку або анімує великі трансформації, ви порушуєте контракт.
Що відключити (і що залишити)
Під prefers-reduced-motion: reduce:
- Відключити плавну прокрутку, ефекти паралаксу, автопрокручувані каруселі, анімовані градієнти фону.
- Зменшити великі трансформаційні переходи (в’їзди бокової панелі), довгі затухання та анімовані підсвітки.
- Залишити короткі, несуттєві мікропереходи, якщо вони не створюють рух по всьому вікну (наприклад, 100ms зміни кольору). Але подумайте про їх відключення для простоти.
Прокрутка — класична підступність
Багато сайтів документації ставлять html { scroll-behavior: smooth; }, бо це виглядає «професійно».
Під зменшеною анімацією це навпаки негарно.
Ваша архітектура токенів і CSS має дозволяти чисто вимкнути це.
Токени анімації: так, токенізувати рух варто
Створіть токени руху:
--motion-duration-fast,--motion-duration-medium--motion-ease-standard--motion-enabledяк концептуальний перемикач (реалізується через перевизначення медіа-запитами)
Потім під зменшеною анімацією встановіть тривалості майже в нуль. Не покладайтеся на аудит кожної строки з transition вручну. Ви пропустите одну. Ви завжди пропускаєте одну.
План реалізації: токени, шари та переозначення
Структура CSS: відділіть токени від CSS компонентів
Помістіть токени в один файл (або згенерований бандл), який підвантажується рано. Потім побудуйте компоненти, що споживають токени.
Антипатерн — змішувати токени у файлах компонентів, бо це робить поверхню токенів неможливою для рев’ю.
Практичне розташування токенів
Рекомендовані файли:
tokens.css: базові + семантичні токени, світла і темна теми.components.css: компоненти, що посилаються на семантичні токени.overrides.css: рідкісні правки на сторінці або інтеграції; ставте це як радіоактивне.
Контракт перемикання теми
Підтримуйте такі режими:
- Система (за замовчуванням): слідуйте
prefers-color-scheme. - Світла (перевизначення користувача): примусити світлу незалежно від системи.
- Темна (перевизначення користувача): примусити темну незалежно від системи.
Реалізуйте через атрибут data-theme на html або body, плюс стан «system», коли атрибут відсутній.
Не робіть одночасно атрибутів і імен класів від різних фреймворків; ви створите конфліктні селектори й проведете один вечір у боротьбі зі специфічністю.
Контракт зменшеної анімації
Використовуйте медіа-запити, а не хаки з боку UA:
@media (prefers-reduced-motion: reduce) { ... }
Уникайте використання JS для «виявлення» зменшеної анімації, якщо це не абсолютно необхідно. CSS надійніший і не залежить від часу виконання скрипта.
Приклад: файл токенів (концептуально)
Я не збираюся тонути вас у повному CSS-дампі теми, але ось шаблон: базові шкали, потім семантичне відображення, потім темні перевизначення.
Тримайте ваші токени компактними й читабельними.
Інструменти і пайплайни: не ставте людей у «гарячий шлях»
Продакшн-темізація — це як продакшн-зберігання: ваші відмови зазвичай буденні і самозвинувачувані. Інструменти допомагають, але лише якщо ви ставите їх як запобіжники, а не як чарівну паличку.
Лінтинг і перевірки консистентності
Використовуйте стиль-лінтер, щоб ловити:
- Хардкодовані кольори у CSS компонентів (коли ви вимагаєте токени).
- Невірні посилання на змінні.
- Надмірно специфічні селектори, що роблять перевизначення токенів неможливими.
Тестування контрасту як сигнал збірки
Не випускайте зміну теми без перевірки контрасту для:
- Основного тексту на фоні
- Посилань на фоні
- Тексту коду на фоні блоку коду
- Приглушеного тексту і кольорів меж (часто першими ламаються в темному режимі)
Вам не потрібна досконалість. Потрібна послідовна політика і спосіб блокувати очевидні регресії.
Візуальні регресійні тести: дешеве страхування
Для сайтів документації візуальні регресії надзвичайно ефективні, бо сторінки шаблонізовані.
Захопіть невелику множину канонічних сторінок:
- Головна сторінка / лендінг
- Сторінка API з таблицями
- Туторіал зі викликами уваги
- Вигляд результатів пошуку
- Сторінка з довгими блоками коду
Запускайте їх у світлому і темному режимах, та з зменшеною анімацією. Так, зменшена анімація впливає на скриншоти, якщо у вас є анімації, що можуть зафіксуватись у середині переходу. Саме в цьому суть: ви ловите недетермінованість.
Два жарті про теми — максимальна безпечна доза
Жарт №2: Якщо ви думаєте, що токени вам не потрібні, ви ніколи не зустрічали «ще цього одного особливого синього» під час квартального ребрендингу.
Практичні завдання: команди, результати та рішення (12+)
Це ті перевірки, які ви виконуєте, коли зміна теми збирається потрапити в реліз, або коли щось «не так» і ви хочете знайти реальну причину. Кожне завдання містить: команду, що означає результат, і рішення, яке ви приймаєте.
Припустимо репозиторій зі зібраним сайтом у dist/ і вихідним CSS у src/.
Завдання 1: Знайти хардкодовані hex-кольори, що обходять токени
cr0x@server:~$ rg -n --hidden --glob '!dist/**' -e '#[0-9a-fA-F]{3,8}\b' src
src/components/sidebar.css:42: border-left: 1px solid #2f3336;
src/pages/api.css:118: color: #1d9bf0;
Що означає результат: У вас є літеральні кольори в CSS компонентів/сторінок.
Рішення: Замініть на семантичні токени (наприклад, --color-border, --color-link) або обґрунтуйте, чому потрібен токен компонента.
Завдання 2: Знайти літерали rgb()/hsl() (також обходять токени)
cr0x@server:~$ rg -n --hidden --glob '!dist/**' -e '\brgb(a)?\(' -e '\bhsl(a)?\(' src
src/components/callout.css:9: background: rgba(29, 155, 240, 0.12);
Що означає результат: Колірні обчислення вбудовані у компоненти.
Рішення: Перенесіть обчислені значення в токени (наприклад, --color-accent-subtle-bg), щоб темний режим міг правильно перевизначати їх.
Завдання 3: Перелічити CSS-змінні, визначені в токенах
cr0x@server:~$ rg -n '^\s*--[a-z0-9-]+\s*:' src/tokens.css | head
12: --space-1: 0.25rem;
13: --space-2: 0.5rem;
14: --radius-1: 6px;
15: --color-bg: #ffffff;
16: --color-fg: #0f1419;
Що означає результат: Швидкий огляд визначень токенів.
Рішення: Підтвердьте послідовність іменування і що семантичні токени існують для кожної важливої поверхні UI (bg/fg/border/link/focus).
Завдання 4: Виявити змінні, що використовуються, але не визначені (опечатки і мертві токени)
cr0x@server:~$ python3 - <<'PY'
import re, pathlib
root = pathlib.Path("src")
defs=set()
uses=set()
for p in root.rglob("*.css"):
t=p.read_text(errors="ignore")
for m in re.finditer(r'--[a-z0-9-]+(?=\s*:)', t): defs.add(m.group(0))
for m in re.finditer(r'var\(\s*(--[a-z0-9-]+)', t): uses.add(m.group(1))
missing=sorted(uses-defs)
print("\n".join(missing[:50]))
print(f"\nmissing_count={len(missing)}")
PY
--color-codblock-bg
--motion-duration-fst
missing_count=2
Що означає результат: Токени, на які посилаються у CSS, не визначені; ймовірні опечатки.
Рішення: Виправити орфографію або навмисно визначити токен. Це класичне джерело регресій «працює в світлому режимі, але не в темному».
Завдання 5: Знайти, де data-theme застосовано в зібраному HTML
cr0x@server:~$ rg -n 'data-theme=' dist/**/*.html | head
dist/index.html:2:<html lang="en" data-theme="dark">
Що означає результат: У збірці жорстко зафіксована тема.
Рішення: Вирішіть, чи це навмисно (наприклад, для прев’ю документації), чи це баг. Більшість продакшн-сайтів повинні за замовчуванням слідувати системним налаштуванням, якщо не збережено вибір користувача.
Завдання 6: Перевірити, що правила зменшеної анімації існують
cr0x@server:~$ rg -n 'prefers-reduced-motion' src/**/*.css
src/tokens.css:148:@media (prefers-reduced-motion: reduce) {
src/components/search.css:77:@media (prefers-reduced-motion: reduce) {
Що означає результат: Маєте явну обробку зменшеної анімації.
Рішення: Переконайтеся, що вона дійсно відключає плавну прокрутку і основні переходи (не лише «duration: 0» в одному компоненті).
Завдання 7: Виявити глобальну плавну прокрутку (часто невірне для зменшеної анімації)
cr0x@server:~$ rg -n 'scroll-behavior\s*:\s*smooth' src/**/*.css
src/base.css:3:html { scroll-behavior: smooth; }
Що означає результат: Увімкнено глобальну плавну прокрутку.
Рішення: Додайте перевизначення для зменшеної анімації: під prefers-reduced-motion: reduce встановіть scroll-behavior: auto.
Завдання 8: Перевірити на наявність «transition: all» (запах продуктивності й доступності)
cr0x@server:~$ rg -n 'transition\s*:\s*all\b' src/**/*.css
src/components/tabs.css:21: transition: all 250ms ease;
Що означає результат: Ви анімуєте все, включно з властивостями, що викликають перерахунок/перерисування.
Рішення: Замініть на явні властивості (наприклад, color, background-color, opacity) і скоротіть тривалість; вимикайте під зменшеною анімацією.
Завдання 9: Перевірити розмір CSS-бандла і його зростання з часом
cr0x@server:~$ ls -lh dist/assets/*.css
-rw-r--r-- 1 cr0x cr0x 184K Dec 29 10:11 dist/assets/site.css
-rw-r--r-- 1 cr0x cr0x 62K Dec 29 10:11 dist/assets/vendor.css
Що означає результат: Розмір бандлів видно і вимірюваний.
Рішення: Якщо ваш CSS набухає від релізу до релізу, підозрійте «обхід токенів» і дублікацію компонентів. Вирішіть: дідуплікувати, розділити або вимагати використання токенів.
Завдання 10: Перевірити обчислені значення в headless-браузері (темна проти світлої)
cr0x@server:~$ node - <<'NODE'
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('file://' + process.cwd() + '/dist/index.html');
const bg = await page.evaluate(() => getComputedStyle(document.documentElement).getPropertyValue('--color-bg').trim());
const fg = await page.evaluate(() => getComputedStyle(document.documentElement).getPropertyValue('--color-fg').trim());
console.log({bg, fg});
await browser.close();
})();
NODE
{ bg: '#0b0f14', fg: '#e7e9ea' }
Що означає результат: Токени резольвляться у фактичні значення в рантаймі.
Рішення: Порівняйте виходи для світлого і темного режимів і переконайтесь, що змінюються семантичні токени, а CSS компонентів залишається стабільним.
Завдання 11: Підтвердити, що сайт поважає системну схему кольорів без примусу
cr0x@server:~$ node - <<'NODE'
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({ colorScheme: 'dark' });
await page.goto('file://' + process.cwd() + '/dist/index.html');
const attr = await page.evaluate(() => document.documentElement.getAttribute('data-theme'));
const bg = await page.evaluate(() => getComputedStyle(document.documentElement).getPropertyValue('--color-bg').trim());
console.log({dataTheme: attr, bg});
await browser.close();
})();
NODE
{ dataTheme: null, bg: '#0b0f14' }
Що означає результат: Сторінка слідує системній перевазі (темний режим) без явного атрибута перевизначення.
Рішення: Залиште цю поведінку, якщо продуктові вимоги не вимагають примусового дефолту. «Система за замовчуванням» зменшує фрикцію для користувачів.
Завдання 12: Знайти використання «!important», що може ламати перевизначення токенів
cr0x@server:~$ rg -n '!\s*important' src/**/*.css
src/components/navbar.css:55: background: var(--color-bg-elevated) !important;
Що означає результат: Наявне підвищення специфічності.
Рішення: Видаліть !important, якщо ви не навмисно боретесь з CSS сторонніх компонентів. Якщо його потрібно зберегти, ізолюйте в шарі інтеграції, щоб базові токени залишалися перевизначуваними.
Завдання 13: Підтвердити, що перевизначення зменшеної анімації дійсно змінює обчислену тривалість переходу
cr0x@server:~$ node - <<'NODE'
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({ reducedMotion: 'reduce' });
await page.goto('file://' + process.cwd() + '/dist/index.html');
const dur = await page.evaluate(() => getComputedStyle(document.documentElement).getPropertyValue('--motion-duration-medium').trim());
console.log({motionDurationMedium: dur});
await browser.close();
})();
NODE
{ motionDurationMedium: '1ms' }
Що означає результат: Ваші токени руху перевизначаються для зменшеної анімації.
Рішення: Якщо це залишиться близько 250ms, ваша CSS-логіка для зменшеної анімації відсутня або не завантажується достатньо рано.
Завдання 14: Перевірити зсув верстки через підвантаження шрифтів (сайти документації чутливі)
cr0x@server:~$ rg -n 'font-display' src/**/*.css src/**/*.scss
src/fonts.css:4: font-display: swap;
Що означає результат: Шрифти налаштовані на swap, що зменшує час «невидимого тексту», але потенційно викликає невеликі зрушення.
Рішення: Для документації зазвичай swap — правильний вибір; якщо ви бачите некрасиві зсуви, налаштуйте метрики шрифтів запасних варіантів або розгляньте optional залежно від UX-цілей.
Швидкий план діагностики
Коли тема документації «неправильна», трюк — уникати дебатів про смак і натомість ізолювати вузьке місце: контраст, відображення токенів, поведінку руху або конфлікти каскаду. Ось порядок, що швидко приводить до відповідей.
Перше: перевірте стан теми і каскад
- Сайт слідує системній перевазі чи примусово встановлює тему через
data-theme? - Файли токенів завантажені перед CSS компонентів?
- Є
!importantправила або скидання фреймворку, що переопреділяють токени?
Чому першим: якщо каскад неправильний, усе інше — шум. Ви не можете дебажити контраст, якщо застосовано неправильну тему.
Друге: перевірте, чи семантичні токени резольвляться в адекватні значення
- Перевірте обчислені
--color-bg,--color-fg,--color-link,--color-border. - Підтвердьте, що темний режим змінює семантичні токени, а не CSS компонентів.
Чому другим: семантичні токени — ваш контракт. Якщо вони неконсистентні, компоненти ніколи не будуть послідовними.
Третє: сигнали доступності — зменшена анімація і контраст
- Під зменшеною анімацією: чи вимкнена плавна прокрутка і чи основні переходи майже нульові?
- Чи видно фокус при навігації клавіатурою в обох темах?
- Перевірте контраст основного тексту, посилань, блоків коду, викликів уваги та таблиць.
Чому третім: це проблеми, що впливають на користувачів і можуть залишатися непоміченими місяцями. Вони не завжди проявляються в «щасливому» тестуванні.
Четверте: продуктивність і детермінованість
- Шукайте «transition: all», великі тіні, фільтри і анімації, що впливають на верстку.
- Переконайтесь, що візуальні регресійні знімки стабільні (немає захоплення в середині переходу).
Чому четвертим: проблеми з продуктивністю теми зазвичай самі-собі зроблені і очевидні, коли знаєш, куди дивитись.
Типові помилки: симптом → корінь проблеми → виправлення
1) «Темний режим виглядає тьмяно, але тільки на деяких сторінках»
Симптом: Більшість сторінок в порядку; деякі мають сірий-на-сірому текст або нечитаємі виклики уваги.
Корінь проблеми: Вкладені контейнери перевизначають семантичний токен (наприклад, --color-fg) або компонент використовує кроки базової шкали безпосередньо.
Виправлення: Обмежте перевизначення токенів кореневими селекторами тем; відрефакторьте компоненти, щоб використовували лише семантичні токени.
2) «Посилання невидимі в темному режимі»
Симптом: Посилання виглядають як звичайний текст, якщо не наводити курсор.
Корінь проблеми: Токен посилання занадто близький до токена фону; токен наведення покладається на підвищення яскравості, що не працює на майже чорних фонах.
Виправлення: Збільште відмінність відтінку і/або товщину підкреслення; визначте --color-link і --color-link-hover явно для кожної теми.
3) «Кільце фокусу зникає на блоках коду і кнопках»
Симптом: Користувачі клавіатури не бачать фокус в деяких компонентах.
Корінь проблеми: Колір кільця фокусу використовує акцент, який зливається з фоном; або стилі фокусу використовують outline: none без заміни.
Виправлення: Створіть --color-focus-ring з високою видимістю в обох темах; забороніть outline: none, якщо не додається краща альтернатива.
4) «Перемикач теми викликає спалах або мерехтіння»
Симптом: Під час перемикання тем спостерігається різкий спалах білого або середній стан палітри.
Корінь проблеми: Файл токенів завантажується пізно або JS встановлює data-theme після первинного візуального рендерингу.
Виправлення: Вставте мінімальний ініціалізуючий скрипт теми в head документа (або уникайте примусу теми за замовчуванням); переконайтеся, що CSS токенів завантажується в критичний шлях.
5) «Зменшена анімація увімкнена, але прокрутка все ще анімується»
Симптом: Користувач скаржиться на дискомфорт від руху; розробник каже «ми підтримуємо зменшену анімацію».
Корінь проблеми: Глобальний scroll-behavior: smooth не перевизначено під зменшеною анімацією; бібліотека JS для плавної прокрутки ігнорує перевагу.
Виправлення: Додайте @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }; обгорніть JS-анімації перевірками переваги.
6) «Таблиці нечитаємі в темному режимі»
Симптом: Сітка ліній зникає; чоргування рядків не відрізняється достатньо.
Корінь проблеми: Використовується один токен межі скрізь; чоргування рядків використовує alpha-оверлеї, що зливаються на майже чорному фоні.
Виправлення: Додайте --color-border-strong і явні токени фонових кольорів рядків таблиці для кожної теми.
7) «Блоки коду схожі на нічний клуб»
Симптом: Кольори синтаксису надто насичені, коментарі надто бляклі, або колір виділення нечитаємий.
Корінь проблеми: Палітра синтаксису не токенізована; скопійована з іншого фонового значення; колір виділення залишено за замовчуванням браузера.
Виправлення: Визначте токени синтаксису (--syntax-keyword, --syntax-string тощо) і токени виділення; перевірте контраст відносно фону блоку коду.
8) «Тепер все — токен, і ніхто нічого змінити не може»
Симптом: Інженери скаржаться, що зміна одного компонента вимагає редагування файлів токенів і очікування дизайну.
Корінь проблеми: Токени включають деталі компонента і мікр-рішення; семантичний шар роздмуханий.
Виправлення: Поверніть деталі компонентів до CSS компонентів; тримайте токени для перехресних рішень (кольори, типографіка, шкала відступів, шкала руху).
Три корпоративні міні-історії з фронту темізації
Інцидент: неправильне припущення про «системний темний режим»
Середньої величини підприємство випустило оновлений портал документації. Команда мала перемикач теми, чистий файл токенів і поведінку «за замовчуванням — система». Все виглядало добре в стендінгу. Реліз відбувся вівторком, бо вівторки дають відчуття хоробрості.
Протягом кількох годин стали надходити звернення в сапорт: «Документація блимає білим при відкритті». Першою думкою команди були проблеми кешу. Другою — CDN. Третьою — «користувачі, мабуть, перебільшують». Остання думка не витримала часу.
Корінь проблеми — неправильне припущення: вони думали, що prefers-color-scheme завжди доступний і стабільний під час першого рендеру. Але їхня реалізація примушувала тему через JS після завантаження, щоб застосувати збережену перевагу. Якщо скрипт завантажувався пізно (повільний пристрій, заблокована ланцюжком сторонніх скриптів, суворий корпоративний проксі), сторінка рендерилась у світлому режимі, а потім переключалась у темний. Спалах. Біль.
Виправлення не було гламурним. Вони вставили крихітний ініціалізуючий скрипт теми у head документа, щоб встановити data-theme до оцінки CSS, і зробили дефолт «системний» таким, що не вимагає JS. Результат: немає спалахів, менше звернень, і команда перестала вважати CSS «фронтенд-магiєю».
Оптимізація, що відбилася під боком: всюди математичні токени
Інша організація спробувала бути розумною: вони хотіли один акцентний токен і обчислювали все інше від нього за допомогою CSS color-mix() та альфа-оверлеїв. У теорії: менше токенів, більше консистентності, легше ребренди.
На практиці: повільне сходження поїзда з розбіжностей браузерів і нечитаємих тонких фонових відтінків.
Перша проблема — передбачуваність. Різні браузери і колірні простори давали трохи різні результати. На темному фоні 12% альфа-оверлей виглядав добре в одному браузері, мутно в іншому і майже непомітно в режимах високої контрастності. Друга проблема — контроль. Коли дизайн хотів зробити фони викликів уваги спокійнішими в темному режимі, команді довелося підправляти формули, що змінювало все інше одразу.
Система також ставала важко відлагоджуваною. Коли хтось питав «який колір цього фону?», відповідь була «це залежить». Приємна відповідь для воркшопу з дизайну і жахлива для оперативного чергування.
Вони врешті повернулись до явних семантичних токенів для ключових поверхонь і станів, залишивши обчислені кольори лише там, де це безпечно й некритично. Кількість токенів зросла. Інцидентів поменшало. Це компроміс, який доводиться робити.
Скучно, але правильно: канонічні сторінки і візуальний diff врятували день
Третя компанія вела сайт документації з кількома продуктовими лініями. Тема мала підтримувати довгі таблиці, вбудовані діаграми і приклади коду трьома мовами. Вони не були особливими. Вони були дисципліновані.
Вони тримали невеликий набір канонічних сторінок у репозиторії: по одній сторінці для кожного «негаразду» з контентом. Кожна зміна теми робила скриншотні дифі у світлому, темному і зменшеному русі. Якщо диф дивував — зміна не заходила до релізу, поки хтось не пояснив її простими словами.
Одного дня, здавалось би безпечна зміна трохи затемнила нейтральну шкалу в темному режимі. Диф показав, що межі таблиць майже зникли, а фон inline-коду злився з фоновим параграфом. Ніхто не помітив цього, переглядаючи одну сторінку, бо більшість сторінок не мали густих таблиць або inline-коду.
Оскільки диф спіймав проблему до релізу, виправлення було тривіальним: підправити два семантичні токени і додати сильніший токен межі. Жодного інциденту. Ніякого хотфіксу. Звичайний PR-рев’ю і всі пішли додому у звичний час.
Контрольні списки / покроковий план
Покроково: побудуйте токенізовану тему документації з нуля
- Визначте поверхні та ролі тексту: фон, піднятий фон, вбудований фон, передній план, приглушений передній план, межа, сильна межа.
- Оберіть нейтральну шкалу з достатньою кількістю кроків, щоб підтримувати підйоми і межі без звернення до альфа-хаків.
- Визначте семантичні токени для посилань, кільця фокусу, виділення і поверхонь коду.
- Визначте токени руху (тривалості + easing) і налаштуйте перевизначення для зменшеної анімації.
- Реалізуйте перемикання тем з дефолтом «система» і користувацьким перевизначенням через
data-theme. - Рефакторьте компоненти щоб споживали лише семантичні токени; дозволяйте токени компонентів лише за реальної потреби.
- Додайте запобіжники: лінтинг на сирі кольори, пошук невизначених токенів, заборона
transition: all. - Додайте канонічні знімки сторінок у світлому/темному/зменшеному русі.
- Випустіть і спостерігайте: слідкуйте за зверненнями в сапорт щодо контрасту, фокусу та руху; це сигнал, а не шум.
Чеклист перед злиттям зміни теми
- Немає сирих кольорів поза файлами токенів (або вони явно обґрунтовані).
- Семантичні токени оновлені для світлої й темної тем.
- Фокус видно на всіх інтерактивних елементах в обох темах.
- Режим зменшеної анімації відключає плавну прокрутку і основні переходи.
- Блоки коду читабельні: фон, виділення, коментарі і inline-код протестовані.
- Таблиці: межі і чоргування рядків залишаються видно в темному режимі.
- Візуальні регресійні дифи переглянуті на канонічних сторінках.
- Перемикання теми не моргає при першому рендері.
Операційний чеклист: діагностика скарги на тему в продакшні
- Відтворіть з налаштуваннями ОС, які вказав користувач (темний режим, зменшена анімація, високий контраст за потреби).
- Перевірте, чи примусово встановлюється атрибут теми пізно через JS (таймінги мережі, блоковані скрипти, проблеми CSP).
- Перегляньте обчислені значення семантичних токенів на постраждалій сторінці.
- Пошукайте локальні перевизначення і
!importantправила поблизу проблемного компонента. - Порівняйте з канонічними сторінками, щоб зрозуміти, чи проблема системна або специфічна для контенту.
Питання й відповіді
1) Де зберігати токени — у CSS-змінних чи генерувати з дизайн-інструмента?
Зберігайте рантаймовий контракт як CSS-змінні. Ви можете згенерувати цей файл з інструмента, якщо хочете, але тримайте вихід токенів читабельним для людини. Коли продакшн ламається, ви хочете дебажити в браузері, а не в експортному пайплайні.
2) Наскільки близько «темний режим як у X» має бути до чистого чорного?
Використовуйте майже чорний для базового фону, не чистий чорний. Чистий чорний може бути різким для читання і ускладнює тонке піднесення поверхонь. Майже чорний дає простір для поверхонь і меж без неонових контурів.
3) Чи нормально використовувати альфа-оверлеї для тонких фонів?
Іноді — так. Альфа-оверлеї крихкі на різних фонах і можуть колапсувати в темному режимі. Віддавайте перевагу явним семантичним токенам для критичних поверхонь (виклики уваги, блоки коду). Використовуйте альфу для некритичних декоративних елементів і тестуйте в обох темах.
4) Чи потрібні окремі токени для блоків коду?
Так, зазвичай. Блоки коду мають інші вимоги: щільний контент, кольори синтаксису, стилі виділення і кнопки копіювання. Ставте їх як окрему поверхню з явним фоном, межею і токенами синтаксису.
5) Який найпростіший перемикач теми, що не мерехтить?
За замовчуванням слідуйте системній перевазі через CSS-медіа-запит. Застосовуйте data-theme лише коли користувач явно обирає світлу або темну тему. Якщо потрібно застосувати при завантаженні, встановіть його до першого рендера невеликим вбудованим скриптом в head документа.
6) Як підтримувати зменшений рух без переписування всього CSS?
Токенізуйте тривалості руху і посилайтесь на них у переходах. Під prefers-reduced-motion: reduce перевизначайте тривалості токенів на майже нуль і відключайте плавну прокрутку. Це покриває більшість випадків без ручного пошуку кожного переходу.
7) Чому не просто використати тему UI-фреймворку і вважати справу зробленою?
Теми фреймворків підходять, поки ваш сайт документації не має блоків коду, таблиць, викликів уваги і компонентів, специфічних для контенту, які не були у «щасливому» шляху фреймворку. Токени дозволяють адаптуватися без форкування всього CSS фреймворку або довічної боротьби зі специфічністю.
8) Скільки токенів — це «занадто багато»?
Коли ви не можете відповісти на «для чого цей токен» без відкриття Figma, у вас забагато. Токени повинні кодувати стабільні рішення. Якщо токен існує лише для того, щоб зробити один компонент трохи іншим, це, ймовірно, належить до CSS компоненту, а не до токена.
9) Токени допомагають з надійністю чи це просто гігієна дизайну?
Вони допомагають надійності, бо зменшують радіус впливу змін. Регулювання семантичного токена може виправити контраст по всьому сайту без редагування CSS компонентів, а регресійні тести можуть зосередитись на шарі токенів. Це менше дивних крайових випадків у продакшні.
Висновок: наступні кроки, що не зіпсують вам тиждень
Будуйте тему так, ніби ви працюєте в продакшні: визначайте контракти, зменшуйте невідомість і тримайте радіус впливу малим.
Токени дизайну — це той самий контракт. CSS-змінні — механізм рантайму. Темний режим і зменшена анімація — не «фічі»; це очікування користувачів, які ви або виконуєте, або ні.
Практичні наступні кроки:
- Аудитуйте ваш CSS на предмет сирих кольорів і
transition: all; перемістіть рішення в семантичні токени. - Реалізуйте темний режим за замовчуванням системи з явним користувацьким перевизначенням через
data-theme. - Додайте токени руху і суворе перевизначення для зменшеної анімації (включно з плавною прокруткою).
- Створіть 5–8 канонічних сторінок і запускайте візуальні дифи у світлому/темному/зменшеному режимах перед злиттям змін теми.
- Зробіть межі, таблиці, блоки коду, кільця фокусу і стилі виділення першокласними токенами. Саме там теми найчастіше ламаються.
Якщо ви зробите це добре, ніхто не похвалить вашу тему документації. Вони просто читатимуть її. Оце перемога.