Вопрос или проблема
Версия Chrome: Версия 130.0.6723.117 (Официальная сборка) (arm64)
Версия Mac OS: Sequoia версия 15.1 (Apple Silicon)
Я хотел бы иметь возможность определять режим светлой/темной темы в Chrome, как это установлено в настройках Chrome. Я могу представить ситуацию, когда пользователь установил настройки внешнего вида Mac OS на светлый режим, а режим внешнего вида Chrome — на темный (или наоборот). В этой ситуации я хотел бы стилизовать свою страницу в соответствии с настройками Chrome.
Однако я не могу определить режим внешнего вида Chrome пользователя, используя подход window.matchMedia
.
Вот мой код, встроенный в HTML-файл:
<html>
<head>
<script language="javascript">
const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)');
const isDarkMode = () => {
return darkModeQuery.matches;
}
const toggleDarkMode = (isDarkMode) => {
if (isDarkMode) {
console.log("Мы в темном режиме");
} else {
console.log("Мы в светлом режиме");
}
}
toggleDarkMode(isDarkMode());
darkModeQuery.addEventListener('change', (event) => {
console.log("Обнаружено изменение режима");
toggleDarkMode(event.matches);
});
</script>
</head>
<body>
<h1>Тест</h1>
</body>
</html>
Когда я перехожу в настройки Mac OS и переключаюсь между светлым и темным режимами, мой слушатель событий срабатывает, и в консоль выводится правильное сообщение:
Настройка внешнего вида Mac OS
Однако, когда я перехожу в настройки Chrome и переключаюсь между светлым и темным режимами, слушатель событий не срабатывает:
Настройки Chrome. Кроме того, функция isDarkMode
всегда возвращает настройки внешнего вида Mac OS, а не настройки режима Chrome.
Этот ответ на StackOverflow.com предполагает, что приведенный выше код должен по крайней мере быть в состоянии определить режим браузера.
Если подход window.matchMedia
не предназначен для определения режима браузера, есть ли другой способ определить режим браузера?
Когда я ставлю точку останова в коде в темном режиме браузера, я вижу, что значение darkModeQuery
следующее: Подсказка отладчика, где darkModeQuery.matches
равно false
. Я ожидал бы, что это будет true
.
Я пробовал обслуживать этот файл с локального веб-сервера (например, python -m http.server
) и просто открывать его из Finder с теми же результатами.
Я прочитал документацию MDN, попробовал предложенный код Gemini и полдюжины вопросов на stackoverflow.com, но ни одно из решений не работает для меня. Может быть, есть какой-то другой фактор, влияющий на это?
Спасибо!
Ответ или решение
Ваш вопрос о том, как правильно определить режим светлой или темной темы в Google Chrome на macOS, очень актуален и требует более глубокого анализа.
Проблема с определением режима
Судя по вашему описанию, вы уже использовали window.matchMedia('(prefers-color-scheme: dark)')
, что является правильным подходом для определения предпочтений пользователя по цветовой схеме, особенно с точки зрения системных настроек. Тем не менее, текущая реализация не позволяет вам определить режим, который установлен именно в Chrome, в отличие от системных настроек macOS.
prefers-color-scheme
: Этот медиа-запрос действительно основывается на предпочтениях системы, а не браузера. Это объясняет, почему при изменении режима в настройках macOS вы видите изменения в JavaScript, но если Chrome настроен отдельно на другой режим, тоwindow.matchMedia
не будет на это реагировать.
Отсутствие поддержки браузера
На данный момент, К сожалению, для определения режима оформления в Chrome через JavaScript нет стандартного метода, так как prefers-color-scheme
в JavaScript привязан к системным настройкам. Chrome просто не предоставляет API, который бы позволял вам отслеживать изменения в собственных настройках.
Возможное решение
Если настоящая необходимость заключается в написании кросс-браузерного решения, вы могли бы использовать подход с CSS-классами, который вы будете менять в зависимости от выбора пользователя. В этом случае, вы можете реализовать переключение тем, которое будет более явно задействовать как системные, так и пользовательские настройки.
document.addEventListener('DOMContentLoaded', (event) => {
const toggleDarkMode = (isDarkMode) => {
if (isDarkMode) {
document.body.classList.add('dark-mode');
} else {
document.body.classList.remove('dark-mode');
}
};
const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)');
toggleDarkMode(darkModeQuery.matches);
darkModeQuery.addEventListener('change', (event) => {
toggleDarkMode(event.matches);
});
// Дополнительный код для ручного переключения
const userPreferenceToggle = document.getElementById('toggle-theme');
userPreferenceToggle.addEventListener('click', () => {
const isDarkMode = document.body.classList.contains('dark-mode');
toggleDarkMode(!isDarkMode);
});
});
Заключение
Текущая реализация window.matchMedia
позволяет вам только взаимодействовать с системными настройками. Для полной адаптации под браузерные настройки, вам придется использовать CSS-классы и, возможно, сохранить предпочтения пользователя в localStorage
или в куках, чтобы они сохранялись при перезагрузке страницы.
Широкое использование методов, связанных с изменением тем, требует детального подхода при проектировании интерфейсов пользователя. Не забудьте протестировать свое решение в разных браузерах и версиях, чтобы убедиться в совместимости и правильной работе кода. Это будет способствовать улучшению опыта пользователей на вашем сайте.