Всем привет! Меня зовут Иван Вахаев, я Frontend‑разработчик digital‑интегратора 5 УГЛОВ.

Сегодня хотел бы поделиться с вами решением проблемы смены фонового цвета с белого на черный в веб‑приложении на React внутри приложения Flutter, которая встречалась у пользователей с темной темой устройства. Темный фон мешал нам, так как люди не могли сканировать QR‑код, который автоматически генерировался в приложении. Ранее, кстати, я рассказывал еще об одном интересном баге с этого же проекта.

В статье описал проблему и рассказал, как мы закрыли баг «темной темы» (так мы его прозвали между собой), который вылезал у 5% пользователей приложения.

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

Предыстория

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

При работе над проектом мы как правило используем одну основную тему, без возможности ее смены. Если ваша операционная система позволяет настраивать тему и устанавливать ее по умолчанию, то она будет передавать эти настройки браузерам, а браузеры, в свою очередь, передают настройки и для веб‑приложений. Ярким примером послужит всем известный MDN, где как раз мы видим, что приложение может отследить системные настройки устройства и подстроиться под него.

Приложение MDN, где можно выбрать нужную тему или оставить системную
Приложение MDN, где можно выбрать нужную тему или оставить системную

Проблема, с которой столкнулись мы

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

Белый цвет, который был использован, не был стандартным и не устанавливался автоматически браузером при разработке. Он был задан нами или наследовался от «родителя».

Наша основная проблема выглядела приблизительно вот так, не считая всего остального приложения
Наша основная проблема выглядела приблизительно вот так, не считая всего остального приложения

Первое «решение», которое могло закрыть все вопросы

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

Как с помощью хука useMediaQuery можно узнать системную тему и использовать эти настройки в своем приложении автоматически
Как с помощью хука useMediaQuery можно узнать системную тему и использовать эти настройки в своем приложении автоматически

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

В данном случае задаем строго темную тему
В данном случае задаем строго темную тему

Благодаря данной настройке мы закрыли баг у 4% процентов пользователей. Остался лишь 1% пользователей, у которых баг уходить не собирался.

Решение для «всех»

Напомню, что веб‑приложение на React было внутри приложения Flutter. К сожалению, разработчик, который работал над этим, не смог помочь нам в решении этой ситуации:(

Основная проблема заключалась в том, что у некоторых пользователей Android OS баг не исчезал, при этом у них были разные версии операционной системы. Пользователи утверждали, что у них установлена светлая тема (хотя подтверждений этому не было). Так как это был мой первый опыт работы с Flutter, мне пришлось искать решение самостоятельно. Но в первую очередь я просто хотел понять, почему все происходит таким образом.

Немного серфинга в интернете позволило мне узнать, что по какой‑то причине Android OS может принудительно изменять цвета. В данном случае он менял только белый фоновый цвет. Обратите внимание, что это происходило в основном, если фоновый цвет не был задан (если кто‑то знает больше об этом, пожалуйста, напишите в комментариях).

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

То что нам и нужно
То что нам и нужно

Где «name» задает имя метаданных, а «content» задает значение.

В итоге, name="color-scheme" указывает на то, какие конкретно цветовые схемы совместимы с нашим документом, а также, основываясь на этом, определяет их порядок предпочтения. Если мы указываем content="only light", то будет использоваться только светлая тема, при которой браузер оставляет фон светлым, а контент делает темным. Более подробную информацию о всех настройках можно найти в документации.

После добавления данного тега в наше SPA-приложение на всех устройствах использовалась только светлая тема.

Комментарии (4)


  1. Grey83
    31.07.2023 11:03
    +1

    Может просто стоило просто изменить цвет фона у QR-кода с белого на другой контрастный?
    Жёлтый, зелёный, светло-серый, etc.


    1. IvanVakhaev Автор
      31.07.2023 11:03

      В любом случае нужно 2 цвета которые бы отлично считывались в сочетании с белым или с черным.
      И я пробовал комбинировать разные цвета, но иногда это плохо сказывалось на читаемость. И в результате стало известно что можно указать вручную использование конкретной темы.


  1. sva89
    31.07.2023 11:03

    Глупый вопрос, но почему бы не генерить QR код со своим фоном?


    1. IvanVakhaev Автор
      31.07.2023 11:03

      В первую очередь ТЗ требовало только светлую тему, поэтому этот вариант не подходил.