Если WebApp не видит тему Telegram, Mini App остается белой в ночном режиме, кнопки теряют контраст или цвета обновляются только после перезапуска. Обычно причина в неподключенном SDK, запуске страницы вне Telegram, жестко заданных CSS-цветах либо отсутствии обработки события themeChanged.

Правильная интеграция использует параметры, которые передает клиент Telegram, применяет безопасные fallback и обновляет интерфейс без перезагрузки при смене светлой и темной темы.

Сначала определите точный симптом

  • Объект Telegram.WebApp отсутствует полностью.
  • themeParams существует, но остается пустым.
  • colorScheme меняется, а CSS остается прежним.
  • Фон обновился, но карточки и поля остались светлыми.
  • Тема работает в Android, но не работает в iOS или Desktop.
  • При первом открытии видна белая вспышка.
  • Цвета правильные внутри Telegram, но ломаются в обычном браузере.

Зафиксируйте версию Telegram, платформу, способ запуска Mini App и значения WebApp.version, platform, colorScheme и themeParams. Не записывайте в общий лог initData и другие пользовательские данные.

Проверьте подключение Telegram WebApp SDK

Объект window.Telegram.WebApp становится доступен после загрузки официального скрипта SDK. Если собственный JavaScript выполняется раньше, код темы увидит undefined и сохранит fallback навсегда.

  • Скрипт SDK подключен на странице Mini App.
  • В Network нет ошибки загрузки или блокировки CSP.
  • Код инициализации запускается после появления объекта WebApp.
  • Ошибка в другом раннем скрипте не останавливает выполнение.
  • Service worker не отдает старую HTML-версию без SDK.
  • Сборщик не подменяет глобальный объект локальной переменной Telegram.

Тестируйте внутри Telegram

Обычная вкладка браузера не получает контекст Telegram автоматически. В ней themeParams могут отсутствовать, и это ожидаемо. Для локальной разработки добавьте контролируемый mock темы, но не принимайте его за проверку настоящего клиента.

  • Откройте Mini App штатной кнопкой или настроенной ссылкой.
  • Проверьте Android, iOS и Desktop отдельно.
  • Сравните запуск из меню, клавиатуры и direct link, если используются разные точки входа.
  • В обычном браузере показывайте нейтральную fallback-тему без ошибок.
  • Не используйте query-параметры тестового mock в production как доверенные данные.

Используйте CSS-переменные Telegram

Telegram предоставляет цвета темы через переменные вида --tg-theme-bg-color, --tg-theme-text-color, --tg-theme-hint-color, --tg-theme-link-color, --tg-theme-button-color и --tg-theme-button-text-color. Дополнительные клиенты могут передавать вторичный фон, цвета секций, header и нижней панели.

  • Фон страницы берется из --tg-theme-bg-color.
  • Основной текст — из --tg-theme-text-color.
  • Вторичный текст — из --tg-theme-hint-color.
  • Карточки и группы — из доступного secondary или section background.
  • Основная кнопка использует button и button text color.
  • Для каждой переменной предусмотрен читаемый fallback.

Поля ThemeParams являются опциональными. Интерфейс не должен становиться прозрачным или нечитаемым, если конкретный цвет не передан старым или отдельным клиентом.

Не ограничивайтесь colorScheme

colorScheme сообщает light или dark, но пользовательская тема Telegram может иметь собственные оттенки. Используйте его для выбора общей логики компонентов, а фактические цвета берите из themeParams или CSS-переменных.

  • Схема light/dark может включать набор теней и иллюстраций.
  • Цвета текста и фона не вычисляются вручную только из названия схемы.
  • Не инвертируйте изображения и иконки автоматически без проверки.
  • Контраст оценивается по фактически полученным цветам.

Обработайте themeChanged

Telegram отправляет событие themeChanged, когда пользователь меняет тему. Если приложение прочитало themeParams только при загрузке, открытая Mini App останется в старых цветах.

  1. Создать одну функцию применения темы.
  2. Вызвать ее после инициализации WebApp.
  3. Подписаться на themeChanged через WebApp.onEvent.
  4. При событии заново прочитать themeParams и colorScheme.
  5. Обновить классы, CSS-переменные и элементы, которые не наследуют стили.
  6. Удалить обработчик при уничтожении компонента, если архитектура приложения этого требует.

Не регистрируйте новый listener при каждом рендере компонента. Иначе одна смена темы запустит обработчик несколько раз и может вызвать лишние перерисовки.

Проверьте CSS-специфичность

Тема может успешно передаваться, но жесткий background: white или цвет UI-библиотеки перекрывает переменную Telegram. Просмотрите computed styles проблемного элемента и источник победившего правила.

  • В компонентах нет постоянных белых и черных фонов без необходимости.
  • Inline style не перекрывает theme class.
  • Стили dark mode приложения не конфликтуют с Telegram.
  • Portal, dropdown и modal получают переменные из доступного корня.
  • iframe имеет собственный набор переменных и не наследует их от родителя.
  • Состояния hover, focus, disabled и error проверены в обеих схемах.

Создайте внутренние семантические токены

Не привязывайте каждый компонент напрямую к десяткам внешних переменных. Сопоставьте Telegram themeParams с собственными токенами интерфейса: page background, surface, primary text, muted text, accent, border и action.

  • Одно место отвечает за mapping и fallback.
  • Компоненты используют семантическое назначение, а не случайный цвет.
  • Обычный браузер получает отдельную базовую тему.
  • Изменение Telegram API не требует правки каждого компонента.
  • Контраст можно проверять централизованно.

Уберите белую вспышку при запуске

До выполнения JavaScript браузер рисует стили из HTML и CSS. Если там задан белый фон, темная Mini App кратко вспыхнет. Используйте CSS-переменную Telegram с fallback уже в базовом stylesheet и минимизируйте время до инициализации приложения.

  • Фон html и body задан сразу.
  • Critical CSS не содержит обязательный белый цвет.
  • Тяжелая загрузка данных не блокирует применение темы.
  • Skeleton и экран загрузки используют те же токены.
  • Смена класса темы не вызывает заметный transition при первом рендере.

Синхронизируйте header и нижнюю панель

Цвет содержимого Mini App и системных областей Telegram может различаться. Если текущая версия API и клиент поддерживают настройку header или background, передавайте согласованный цвет через штатные методы, а не пытайтесь перекрыть системный интерфейс HTML-элементом.

Учитывайте, что доступные параметры зависят от версии. Проверяйте поддержку метода и сохраняйте корректный вид без него.

Проверьте старые клиенты и версии

  • Сравните WebApp.version на проблемном устройстве.
  • Не считайте новые поля обязательными.
  • Перед вызовом метода проверяйте его наличие или поддержку версии.
  • Fallback-тема остается читаемой без secondary и section цветов.
  • Обновление Telegram предлагается как диагностический шаг, а не единственное исправление.

Тема внутри iframe

Если часть интерфейса загружена в iframe, CSS-переменные родителя туда не переходят. Передавайте только разрешенный набор цветов через контролируемый postMessage, проверяйте origin и применяйте значения внутри документа iframe.

Не отправляйте вместе с темой initData, токены и пользовательскую информацию стороннему iframe.

Не доверяйте теме как данным безопасности

themeParams нужны для оформления и не подтверждают личность пользователя. Авторизация сервера строится на проверенном initData по правилам Telegram. Нельзя выдавать доступ, роль или скидку по colorScheme, platform и любым значениям, полученным только в браузере.

Проверьте контраст и доступность

  • Основной и вторичный текст читаются на соответствующем фоне.
  • Кнопка различима в normal, pressed и disabled состоянии.
  • Ошибка обозначается не только цветом.
  • Focus виден при использовании клавиатуры.
  • Иконки наследуют currentColor или получают согласованный токен.
  • Графики и статусы остаются понятными в пользовательской теме.

Диагностика по шагам

  1. Открыть Mini App внутри Telegram и проверить window.Telegram.WebApp.
  2. Зафиксировать version, platform, colorScheme и набор ключей themeParams.
  3. Проверить наличие --tg-theme-* в computed styles корневого элемента.
  4. Найти жесткие CSS-цвета и конфликтующие правила.
  5. Переключить тему Telegram при открытой Mini App.
  6. Убедиться, что themeChanged вызывает один обработчик.
  7. Проверить modal, dropdown, iframe и экран загрузки.
  8. Повторить тест в Android, iOS и Desktop.

Типичные ошибки

  • Тестировать только в обычном браузере и ждать реальные themeParams.
  • Читать WebApp до загрузки SDK.
  • Задать background white во всех карточках.
  • Использовать только colorScheme и игнорировать реальные цвета.
  • Считать все поля ThemeParams обязательными.
  • Не подписываться на themeChanged.
  • Добавлять listener при каждом рендере.
  • Передавать в сторонний iframe тему вместе с секретными данными.
  • Использовать initDataUnsafe для серверной авторизации.

Профилактика

Сделайте отдельную страницу или режим проверки темы со всеми компонентами: текстом, полями, карточками, кнопками, состояниями, modal и skeleton. Запускайте ее в Telegram на светлой, темной и пользовательской теме после обновления SDK или UI-библиотеки.

  • Цвета проходят через семантические токены.
  • У каждой переменной есть fallback.
  • themeChanged покрыт тестом состояния.
  • CSP разрешает только необходимый официальный SDK.
  • Ошибки темы не блокируют основной сценарий Mini App.

Итог

Когда WebApp не видит тему Telegram, нужно проверить SDK и точку запуска, затем themeParams, CSS-переменные и специфичность стилей. Интерфейс должен читать опциональные параметры с fallback и повторно применять их при событии themeChanged.

Если нужно исправить тему Telegram Mini App, я могу проверить инициализацию SDK, построить mapping themeParams в токены интерфейса, убрать конфликтующие цвета, настроить themeChanged и протестировать компоненты в Android, iOS и Desktop.