Работа агента на практике · · 15 мин чтения

Светлая, тёмная и авто: тема сайта с понятным поведением

Практический разбор сайта GrantTap: система, ручной выбор, отказ хранилища, первый рендеринг, соседние вкладки и читаемые технические страницы.

ИллюстрацияОбраз статьи создан специально для этого материала. Настоящие снимки GrantTap ниже имеют отдельные подписи.

Автоматическая тема кажется небольшой функцией, пока не проверишь её на настоящем продуктовом сайте. Главная выглядит хорошо, руководство открывается с яркой вспышкой, пример команды становится нечитаемым, а соседняя вкладка игнорирует только что выбранное оформление. Для таких ошибок не требуется сложное приложение. Они появляются, когда тема считается кнопкой замены фона, хотя на деле связывает намерение пользователя, системное оформление, постоянное хранилище, начальный рендеринг и каждый компонент, который самостоятельно выбирает цвет. Полезная тема сначала делает эту связь предсказуемой и только потом украшает страницу, которую человек пришёл читать или использовать для решения конкретной технической задачи.

Сайт GrantTap подходит для практического разбора: в нём есть главная страница, длинное руководство, технические статьи, цены, юридическая информация и реальные скриншоты продукта. Читатель может прийти прямо из поиска, минуя главную. Кто-то предпочитает светлые страницы днём, кто-то следует системе, а кто-то оставляет явный Dark, даже когда компьютер переключается в Light. Здесь объясняются решения и проверки для режимов Auto, Light и Dark на сайте. Это не описание новой настройки нативного приложения. Сгенерированные иллюстрации передают идеи, а настоящие браузерные снимки обозначаются отдельно: изображение, похожее на интерфейс, само по себе не доказывает работу реализованной функции.

Короткая проверка

Используйте отдельную тестовую Task и только разрешённую рабочую папку.

  1. Проверьте Auto и ручной режим

    Выберите Auto и смените системный режим. Затем выберите Light, снова смените систему и проверьте приоритет ручного выбора.

  2. Откройте соседнюю вкладку

    Измените тему в одной вкладке, проверьте вторую, перезагрузите её и проверьте сохранённый режим.

  3. Прочитайте длинную страницу на телефоне

    Проверьте заголовки, подписи, код, фокус и навигацию в обоих режимах. Поздний скриншот не доказывает отсутствие начальной вспышки.

Отделите выбранный режим от отображаемых цветов

Храните предпочтение как одно из трёх значений: auto, light, dark. Отображаемое оформление имеет только два значения: светлое и тёмное. В Auto его определяет текущая системная настройка. Явный Light или Dark остаётся явным, даже когда совпадает с системой. Это различие проявится при следующем системном переключении. Если сохранить только вычисленный цвет, пользователь, выбравший Auto вечером, неожиданно окажется навсегда привязан к Dark. Сайт запомнит вчерашнее наблюдение вместо намерения человека. Такая ошибка незаметна при первом клике и поэтому легко проходит поверхностную проверку готового переключателя.

Селектор должен показывать сохранённое предпочтение, а не просто текущий цвет фона. При тёмной системе Auto и Dark выглядят одинаково, но обещают разное последующее поведение. Контрол с тремя вариантами делает это обещание понятным. Двоичная кнопка с солнцем и луной не выражает то же состояние без дополнительных действий или пояснения. Контролу нужны доступное имя и нормальная работа с клавиатуры. На узком экране он должен помещаться рядом с языком и навигацией, не растягивая страницу шире viewport и не закрывая важные ссылки. Видимость элемента в desktop-макете ещё не подтверждает удобство его использования на телефоне.

Правило вычисления оформления следует определить один раз для всего сайта. Иначе руководство, маркетинговая шапка и юридический footer начнут по-разному трактовать отсутствие значения, старую настройку и неожиданную строку. Проверяйте сохранённые данные по трём разрешённым вариантам. Неизвестные значения должны приводить к безопасному стандартному режиму, а не без проверки попадать в имена классов или атрибуты. Получается небольшая модель, которую легко объяснить и протестировать: посетитель выбирает предпочтение, а сайт вычисляет оформление из этого предпочтения и, при необходимости, текущей системной настройки. Разделённая модель помогает локализовать ошибки, не перенося логику выбора в каждый компонент.

Оригинальная AI-иллюстрация идеи статьи. Это не экран приложения и не результат измерения.
ИллюстрацияОригинальная AI-иллюстрация идеи статьи. Это не экран приложения и не результат измерения.

Auto должен реагировать в уже открытой вкладке

Автоматический режим должен следовать операционной системе без перезагрузки страницы. Браузер предоставляет системное предпочтение через media query prefers-color-scheme. Разбор media query на web.dev объясняет механизм и связь со стилями страницы. Когда сайт поддерживает явное переопределение, одной подписки на системное событие недостаточно. Обработчик должен снова учитывать выбранный режим, прежде чем применять новое системное оформление. Иначе человек выбирает Light, вечером компьютер переключается в Dark, а сайт неожиданно отменяет явное решение пользователя. Формально событие обработано, но пользовательский контракт нарушен.

Проверьте два противоположных сценария в одной вкладке. Сначала выберите Auto, измените эмулируемое системное предпочтение и убедитесь, что страница последовала за ним. Затем установите явный Light, переключите систему в Dark и проверьте, что страница осталась светлой. Повторите для явного Dark. Наблюдайте и реальные цвета, и значение контрола. Тест регистрации listener не подтверждает видимый результат. Важное утверждение состоит в том, что текущее предпочтение правильно определяет оформление после внешнего события, а не в том, что конкретная функция подписки была вызвана ожидаемое число раз в искусственном окружении.

Подпискам нужен управляемый жизненный цикл. Создавайте их в одном контроллере уровня сайта и удаляйте при его завершении. Дополнительный listener на каждом переходе способен породить повторную работу и трудно воспроизводимые обновления. Для темы не нужны сеть, аккаунт и постоянное соединение с локальным coding-агентом. Это браузерное предпочтение для чтения сайта. Простая граница повышает надёжность: визуальный выбор не зависит от состояния чужой инфраструктуры и не создаёт дополнительные фоновые запросы. Даже если агент на компьютере недоступен, посетитель должен спокойно открыть руководство и выбрать удобное оформление.

Сохраняйте намерение и обрабатывайте отказ хранилища

Возвращающийся посетитель ожидает, что явный выбор переживёт переходы и перезагрузку. Local storage подходит для такого браузерного предпочтения, но чтение и запись могут завершаться ошибкой. Настройки приватности, ограничения контекста и заполненное хранилище не должны запрещать изменение текущей страницы. Обрабатывайте доступ отдельно, проверяйте прочитанное и сохраняйте выбор в памяти, если запись не удалась. Хранилище только для чтения способно вернуть прежнее значение после неудачной записи. Немедленное повторное чтение не должно молча отменять только что выбранный пользователем режим и возвращать интерфейс к старому состоянию.

Запасное поведение может быть скромным: оформление работает на текущей странице, хотя сохранение между будущими посещениями недоступно. Для несущественного предпочтения не нужен драматичный экран ошибки приложения. Но и обещать успешное постоянное сохранение нельзя. Такой сценарий стоит проверить отдельно, потому что обычный профиль браузера редко его воспроизводит. Подготовьте случай, где storage возвращает старый режим, но отвергает новую запись. Затем убедитесь, что контрол и страница удерживают новый выбор во время текущего сеанса. Проверка должна наблюдать итоговое состояние, а не только перехваченный exception или отсутствие падения функции.

Если раньше у руководства был собственный ключ темы, задайте явное правило миграции. Корректное новое глобальное значение должно иметь приоритет. Когда его нет, корректная старая настройка руководства может сохранить привычный режим посетителя. Повреждённые старые данные не должны создавать четвёртый вариант. Опишите приоритет в коде и проверьте его один раз. Без общего правила главная начнёт восстанавливать одно предпочтение, а руководство другое, хотя оба компонента формально успешно используют постоянное хранилище. Миграция небольшого ключа полезна именно потому, что убирает неожиданное расхождение между уже знакомыми пользователю частями одного сайта.

Согласуйте вкладки без круговой перезаписи

Изменение темы в одной вкладке должно обновлять другую вкладку того же сайта, когда браузер передаёт соответствующее событие хранилища. Событие storage предназначено для изменений из другого документа, использующего ту же область хранения. Окно, выполнившее запись, само это событие обратно не получает. Это различие описано в справочнике MDN о storage event. Поэтому полная реализация непосредственно обрабатывает локальный выбор и отдельно слушает изменения соседних вкладок. Попытка использовать только один механизм оставит либо текущую страницу, либо остальные открытые страницы в прежнем оформлении до следующей перезагрузки.

Не заставляйте каждый listener снова записывать полученное значение. Наблюдателю обычно нужно обновить представление, а не становиться ещё одним автором того же предпочтения. Запись только при явном действии пользователя уменьшает лишние события и исключает ненужные циклы. Полученное внешнее значение проверяйте, а Auto вычисляйте с учётом текущего системного наблюдения принимающей вкладки. Если хранилище очищено, применяйте описанный стандартный режим. Проверьте очистку отдельно от обычного переключения Light в Dark. Отсутствие значения — полноценное состояние интерфейса, которое обязательно встретится у нового посетителя или после удаления данных браузера.

Для приёмки откройте две настоящие браузерные страницы. Установите режим в первой, убедитесь в изменении второй, перезагрузите вторую и проверьте сохранённый выбор. Затем верните Auto и переключите эмулируемую систему. Одностраничный unit-тест полезен для ветвей обработчика, но две страницы проверяют реальное взаимодействие документов и storage. Сохраняйте оба вида доказательств: узкие тесты помогают быстро найти регрессию, браузерный сценарий подтверждает согласованность настоящих границ. При этом тестовая вкладка не должна использовать другой origin или временный домен, иначе она проверяет независимое хранилище и не может подтвердить синхронизацию одной и той же настройки.

Применяйте начальную тему до отображения контента

Страница, которая сначала рисуется в неправильном режиме и исправляется после hydration, создаёт заметную вспышку. На тёмном экране ночью это особенно неприятно. Прочитайте небольшое проверенное предпочтение достаточно рано и примените вычисленное оформление к документу до основного отображения. Bootstrap должен заниматься только оформлением. Ему не следует загружать пользовательские данные, разбирать большое состояние приложения и ждать подключения агента. Для выбора одной из двух палитр нужна минимальная работа. Усложнение раннего кода повышает риск задержать весь документ ради настройки, которая должна быть практически мгновенной.

При server rendering сервер не знает автоматически о значении, лежащем только в local storage посетителя. Начальному HTML и клиентскому контроллеру нужно понятное соглашение об атрибутах корневого элемента, которыми они управляют. Узко ограниченное подавление ожидаемого hydration-warning для оформления корня отличается от сокрытия любых расхождений по всей странице. Проверьте, что title, язык, заголовки, ссылки и основной текст статьи по-прежнему присутствуют в исходном HTML. Инициализация темы не должна откладывать полезный контент до завершения JavaScript. Посетитель и поисковая система должны получать читаемую страницу независимо от скорости запуска клиентского приложения.

Проверяйте холодный прямой вход в главу руководства и статью, а не только переход с уже открытой главной. Зафиксируйте начальное оформление при обеих системных настройках и сохранённом явном переопределении. Скриншот спустя несколько секунд легко пропустит первоначальную вспышку. Отдельно снимите установившуюся страницу для оценки геометрии и контраста. Начальный и окончательный рендеринг имеют разные условия приёмки: один поздний снимок не доказывает оба. Убедитесь также, что повторное открытие не требует промежуточного посещения главной, иначе прямые ссылки из поиска будут вести себя хуже внутренней навигации сайта.

Задавайте цвета по назначению элементов

Определите роли: фон страницы, панель, основной текст, вторичный текст, граница, акцент, фокус и статус. Компоненты должны использовать эти роли вместо независимых предположений о тёмном фоне. Светлая палитра часто обнаруживает скрытые жёсткие значения в подписях, полях, блоках кода и разделителях. Поиск по стилям полезен, но нужен и настоящий рендеринг. Текстовый поиск не определяет итоговый контраст полупрозрачного элемента на нескольких слоях. Вычисленный цвет зависит от композиции, поэтому корректный отдельный токен ещё не доказывает, что человек сможет прочитать его в конкретной карточке или форме на странице.

Избегайте слепой замены коротких фрагментов цветовых значений. Короткая hexadecimal-последовательность может входить в более длинный токен, после чего замена оставит неправильный CSS, который браузер молча проигнорирует. Меняйте полные объявления или конкретные переменные, затем смотрите computed colors представительных компонентов. Примеры команд должны читаться в обоих режимах, включая выделение текста и горизонтальную прокрутку. Статья может выглядеть отлично сверху и делать почти невидимой самую полезную диагностическую команду ниже. Для технического руководства это функциональный дефект: читатель не получает инструмент решения своей задачи, даже если общая композиция страницы выглядит аккуратно.

Сохраняйте фирменный акцент, но не поручайте одному цвету передавать весь смысл. Доставка, предупреждения и успех должны иметь слова либо понятные значки. Смена темы не должна превращать ошибку в неоднозначную оранжевую точку. Проверьте hover, клавиатурный фокус, disabled-состояния и нативное меню select. Общие токены дают единый словарь, но не отменяют осмотр компонентов: геометрия и взаимодействие влияют на восприятие цвета. Особенно внимательно проверяйте второстепенные подписи, потому что именно их часто намеренно делают приглушёнными и затем случайно опускают ниже удобной читаемости на новой светлой поверхности сайта.

Отдельная ImageGen-иллюстрация сценария. Настоящие наблюдения и скриншоты обозначаются отдельно.
ИллюстрацияОтдельная ImageGen-иллюстрация сценария. Настоящие наблюдения и скриншоты обозначаются отдельно.

Сохраняйте правдивость скриншотов

Настоящий скриншот продукта содержит собственную зафиксированную палитру. Автоматическая перекраска под тему сайта может исказить приложение или сделать подписи нечитаемыми. Сохраняйте изображение и подбирайте подходящую рамку вокруг него. Исторические снимки обозначайте реальным контекстом, когда руководству нужен старый экран. Светлая тема сайта не означает, что старый нативный скриншот переснят в светлой теме приложения. Читателю важно различать пиксели, которые подтверждают состояние продукта, и окружающее оформление статьи. Иначе красивый материал создаёт неверное представление о доступных настройках самого приложения и перестаёт быть надёжной инструкцией для владельца телефона.

Редакционные иллюстрации можно специально создавать в палитре, подходящей обоим режимам. Это не делает их доказательством интерфейса. Давайте подписи с объяснением идеи и обозначайте изображения как иллюстрации. Для материала о темах полезная тройка может показывать выбор предпочтения, автоматическое вычисление и проверочную среду. Каждое изображение должно добавлять отдельную мысль, а не трижды повторять декоративную композицию. Реальный браузерный снимок храните отдельно, с датой и средой в редакционной записи. Такая дисциплина не мешает визуальной выразительности: она помогает использовать красивое изображение по назначению, сохраняя доверие к настоящим доказательствам работы сайта.

Посмотрите загрузку изображений и соседние поверхности на мобильном соединении. Большие скриншоты способны составить основную массу статьи, а декоративный файл случайно задержать главный заголовок. Выбирайте подходящие размеры и форматы, резервируйте место в layout и оставляйте важный текст в HTML. Читатель не должен увеличивать картинку ради основного чеклиста приёмки. Изображения поддерживают объяснение, а выделяемые заголовки, команды и подписи делают материал полезным людям, assistive technology и поисковым системам. Хорошая редакционная графика не заменяет рабочую инструкцию; она помогает быстрее понять связи, которые уже доступны и в текстовом виде на странице.

Проверяйте семейства страниц, а не одну главную

Глобальное предпочтение требует проверки глобальной поверхности. Включите главную, индекс статей, длинный материал, индекс руководства, отдельную главу, цены, поддержку, юридическую страницу и существующие control-разделы, использующие общий слой оформления. Проверьте прямой вход и навигацию. Одна шапка может находиться над разными поверхностями, а встроенные формы и кодовые панели иметь собственные стили. Начните с небольшой представительной матрицы и расширяйте её для семейств с отдельными компонентами. Механическое повторение всех URL не заменяет осмысленного выбора страниц, на которых действительно отличаются цветовые роли, интерактивные элементы и ограничения мобильного layout.

Для GrantTap полезно сочетать узкую мобильную и широкую desktop-геометрию с Light, Dark и Auto. Добавьте английские и русские страницы: длина текста меняет положение языкового контрола и тему в шапке. Убедитесь, что документ не прокручивается горизонтально, переключатель доступен, содержание статьи работает и фиксированные элементы ничего не закрывают. Автоматические снимки помогают увидеть очевидные расхождения, но представительные кадры нужно посмотреть самостоятельно. Валидный CSS всё равно может дать неудобную шапку телефона или слишком бледную подпись. Проверка по числу успешных сетевых ответов этого не обнаружит, потому что сервер корректно доставит даже визуально неудобную страницу.

Успешный headless Chromium не означает проверку каждого физического браузера. Он предоставляет повторяемое доказательство для конкретного движка и конфигурации. Safari, мобильные панели браузера, нативные меню и accessibility-настройки могут вести себя иначе. Записывайте фактически проверенную среду и сохраняйте небольшой ручной список для остальных целей. Это полезнее универсального обещания «работает везде». Матрица нужна для видимого и воспроизводимого поведения, а не для производства уверенности за пределами реальных проверок. Если конкретный телефон не участвовал, его отсутствие остаётся ограничением доказательства, даже когда все автоматические desktop-сценарии закончились успешно без единой ошибки JavaScript.

Не связывайте поисковую идентичность с оформлением

Light и Dark — предпочтения чтения одной страницы. Они не должны создавать конкурирующие индексируемые URL или отдельные сущности статьи. Canonical, переведённые alternates, даты публикации, structured data и заголовки остаются стабильными при смене цветов. Социальная share-карточка должна читаться как самостоятельное изображение: внешний сервис не наследует local storage посетителя. Подготовьте отдельную горизонтальную карточку вместо предположения, что высокий скриншот приложения удачно обрежется в мессенджере. Правильные пропорции и короткая понятная подпись помогают узнаваемости страницы, но не требуют публикации новой копии статьи для каждого визуального режима, устройства и способа открытия ссылки.

Язык страницы определяйте по URL и реальному содержимому независимо от темы. Открывший русскую статью посетитель должен получить русские текст и metadata, даже если раньше смотрел английскую главную в Dark. Это разные предпочтения с разным отношением к URL. Listener темы не должен переписывать язык или навигацию. Языковая ссылка, в свою очередь, должна сохранять браузерный режим без нового отдельного ключа на каждую локаль. Разделение обязанностей облегчает и accessibility, и поисковое поведение. Проверять их можно независимо, а ошибки не приходится объяснять сложным взаимодействием двух настроек, которые по назначению вообще не должны управлять друг другом.

После релиза проверьте публичный исходный HTML, ответ share-image, sitemap и ссылки статей вместе с браузерным интерфейсом. Локальный тест исходника не доказывает, что production-образ получил новые файлы. Зафиксируйте развёрнутую ревизию и сравните видимый результат с проверенным кандидатом. Ранжирование и индексация остаются внешними результатами, которые нельзя гарантировать успешным deploy. Доказуемое улучшение конкретнее: целостная доступная страница с точными metadata и стабильным содержимым во всех поддерживаемых режимах. Именно такой результат можно показать владельцу сайта, повторно проверить после обновления фреймворка и передать следующему разработчику без расплывчатых обещаний о будущих позициях поиска.

Оставьте воспроизводимые условия приёмки

Итоговый список должен описывать поведение: Auto следует живому изменению системы, явный режим его игнорирует, reload удерживает успешно сохранённый выбор, соседняя вкладка видит обновление, отказ записи не отменяет выбор текущего сеанса, прямой вход начинается в нужном оформлении. Добавьте читаемый текст, заметный фокус, мобильную геометрию, неизменённые реальные скриншоты и стабильный canonical. Такие утверждения переживут смену фреймворка, storage-helper и структуры компонентов. Тесты, привязанные только к имени текущей функции, менее долговечны. Проверяющий должен понимать ожидаемый результат, даже если никогда не видел внутреннего кода, который отвечает за начальную установку атрибутов документа.

Лучший итог выглядит обыденно: человек открывает руководство GrantTap в удобном режиме, выполняет команду, переходит к статье и продолжает читать, не думая о состоянии темы. Для такого спокойного опыта нужно внимательно проверить границы небольших систем: серверный HTML, браузерное хранилище, media query, стили компонентов и редакционные файлы. Работа оправдана, потому что делает техническую информацию удобнее. Сформулируйте предпочтение как понятный контракт, проверьте переходы и сохраните честные сведения об окружениях, участвовавших в тестировании. Тогда красивое оформление будет поддерживать реальную полезность сайта, а не скрывать поведенческие ошибки за удачным первым скриншотом главной страницы.

Настоящий снимок сайта GrantTap из Chromium, кандидат выпуска 5 ноября 2026 года, 390 × 844 CSS-пикселя, светлая тема. Это сайт, а не настройка темы нативного приложения.
Настоящий снимок GrantTapНастоящий снимок сайта GrantTap из Chromium, кандидат выпуска 5 ноября 2026 года, 390 × 844 CSS-пикселя, светлая тема. Это сайт, а не настройка темы нативного приложения.

Источники

ДалееАгент изменил файл, а приложение старое: проверьте checkout →