Всем привет! Меня зовут Иван Вахаев, я Frontend‑разработчик digital‑интегратора 5 УГЛОВ.
Сегодня хотел бы поделиться с вами решением проблемы смены фонового цвета с белого на черный в веб‑приложении на React внутри приложения Flutter, которая встречалась у пользователей с темной темой устройства. Темный фон мешал нам, так как люди не могли сканировать QR‑код, который автоматически генерировался в приложении. Ранее, кстати, я рассказывал еще об одном интересном баге с этого же проекта.
В статье описал проблему и рассказал, как мы закрыли баг «темной темы» (так мы его прозвали между собой), который вылезал у 5% пользователей приложения.
Возможно, многие уже сталкивались с этой задачкой и ее решением, скорее материал будет полезен для новичков, которые наткнулись на это препятствие впервые.
Предыстория
Все мы знаем, что во многих веб‑приложениях есть возможность менять тему. Обычно предлагаются две опции: светлая и темная. Однако также может быть настройка для слабовидящих людей, с более контрастными цветами и увеличенным шрифтом, или для людей с цветовой слепотой. В последнем случае учитывается особенности дизайна, и нет необходимости в наличии дополнительной темы.
При работе над проектом мы как правило используем одну основную тему, без возможности ее смены. Если ваша операционная система позволяет настраивать тему и устанавливать ее по умолчанию, то она будет передавать эти настройки браузерам, а браузеры, в свою очередь, передают настройки и для веб‑приложений. Ярким примером послужит всем известный MDN, где как раз мы видим, что приложение может отследить системные настройки устройства и подстроиться под него.

Проблема, с которой столкнулись мы
На проекте в связке с Flutter (в данном случае приложение просто выполняло функции браузера, без возможности перехода на другой домен и скрытой адресной строкой), у 5% пользователей обнаружился баг: в основном только белый фоновый цвет менялся на черный (с #FFFFFF на #212121).
Белый цвет, который был использован, не был стандартным и не устанавливался автоматически браузером при разработке. Он был задан нами или наследовался от «родителя».

Первое «решение», которое могло закрыть все вопросы
Поскольку мы пользуемся MUI и настройка темы для всего приложения была задана для него, то в первую очередь я пошел туда, с задачей узнать, есть ли какой‑то инструмент внутри библиотеки для решения данного бага. И о чудо, действительно есть, если зайти на сайт MUI, то представлено несколько примеров по настройке темы.

Но также мы можем жестко задать только одну тему, обойдя системную.

Благодаря данной настройке мы закрыли баг у 4% процентов пользователей. Остался лишь 1% пользователей, у которых баг уходить не собирался.
Решение для «всех»
Напомню, что веб‑приложение на React было внутри приложения Flutter. К сожалению, разработчик, который работал над этим, не смог помочь нам в решении этой ситуации:(
Основная проблема заключалась в том, что у некоторых пользователей Android OS баг не исчезал, при этом у них были разные версии операционной системы. Пользователи утверждали, что у них установлена светлая тема (хотя подтверждений этому не было). Так как это был мой первый опыт работы с Flutter, мне пришлось искать решение самостоятельно. Но в первую очередь я просто хотел понять, почему все происходит таким образом.
Немного серфинга в интернете позволило мне узнать, что по какой‑то причине Android OS может принудительно изменять цвета. В данном случае он менял только белый фоновый цвет. Обратите внимание, что это происходило в основном, если фоновый цвет не был задан (если кто‑то знает больше об этом, пожалуйста, напишите в комментариях).

Ну и что же делать в таком случае? Старый добрый тег meta, который решит эту задачку.

Где «name» задает имя метаданных, а «content» задает значение.
В итоге, name="color-scheme" указывает на то, какие конкретно цветовые схемы совместимы с нашим документом, а также, основываясь на этом, определяет их порядок предпочтения. Если мы указываем content="only light", то будет использоваться только светлая тема, при которой браузер оставляет фон светлым, а контент делает темным. Более подробную информацию о всех настройках можно найти в документации.
После добавления данного тега в наше SPA-приложение на всех устройствах использовалась только светлая тема.
Комментарии (4)
sva89
31.07.2023 11:03Глупый вопрос, но почему бы не генерить QR код со своим фоном?
IvanVakhaev Автор
31.07.2023 11:03В первую очередь ТЗ требовало только светлую тему, поэтому этот вариант не подходил.
Grey83
Может просто стоило просто изменить цвет фона у QR-кода с белого на другой контрастный?
Жёлтый, зелёный, светло-серый, etc.
IvanVakhaev Автор
В любом случае нужно 2 цвета которые бы отлично считывались в сочетании с белым или с черным.
И я пробовал комбинировать разные цвета, но иногда это плохо сказывалось на читаемость. И в результате стало известно что можно указать вручную использование конкретной темы.