MUI (Material-UI) предоставляет встроенные механизмы для автоматического определения и применения темы интерфейса в зависимости от настроек операционной системы пользователя. Это особенно полезно для реализации тёмного и светлого режима, который подстраивается под системные предпочтения.
useMediaQueryMUI использует хук useMediaQuery для отслеживания
предпочтений пользователя. Основное правило — использовать
CSS-медиа-запрос prefers-color-scheme.
Пример базовой реализации:
import { useMemo } from 'react';
import { createTheme, ThemeProvider, useMediaQuery } from '@mui/material';
function App() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const theme = useMemo(
() =>
createTheme({
palette: {
mode: prefersDarkMode ? 'dark' : 'light',
},
}),
[prefersDarkMode],
);
return (
<ThemeProvider theme={theme}>
{/* Компоненты приложения */}
</ThemeProvider>
);
}
export default App;
Ключевые моменты:
useMediaQuery('(prefers-color-scheme: dark)')
возвращает true, если система настроена на тёмный
режим.useMemo используется для предотвращения лишнего
пересоздания темы при каждом рендере.ThemeProvider обеспечивает передачу темы всем
компонентам MUI.Система пользователя может изменять тему на лету (например, смена
времени суток на iOS или Android). Хук useMediaQuery
автоматически обновляет значение, что позволяет темам
переключаться динамически без перезагрузки страницы.
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)', {
noSsr: true,
});
Опция noSsr: true необходима, если приложение рендерится
на сервере, чтобы избежать рассинхронизации темы между сервером и
клиентом.
MUI позволяет создавать кастомизированные палитры, которые меняются в зависимости от системной темы:
const getDesignTokens = (mode) => ({
palette: {
mode,
...(mode === 'light'
? {
primary: { main: '#1976d2' },
background: { default: '#f5f5f5' },
}
: {
primary: { main: '#90caf9' },
background: { default: '#121212' },
}),
},
});
const theme = useMemo(() => createTheme(getDesignTokens(prefersDarkMode ? 'dark' : 'light')), [prefersDarkMode]);
Преимущества такого подхода:
Для улучшения UX можно комбинировать системную тему и
пользовательский выбор. Например, сохранять предпочтение в
localStorage и использовать его как приоритет над системной
темой:
const storedMode = localStorage.getItem('themeMode');
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const mode = storedMode || (prefersDarkMode ? 'dark' : 'light');
Такой подход обеспечивает:
CssBaseline для согласованности стилейMUI рекомендует применять компонент CssBaseline
совместно с темой для корректного отображения фона и цвета текста на
уровне всего документа:
import { CssBaseline } from '@mui/material';
<ThemeProvider theme={theme}>
<CssBaseline />
{/* Приложение */}
</ThemeProvider>
CssBaseline автоматически подстраивает цвета под
выбранный режим (light или dark) и устраняет
дефолтные стили браузера, обеспечивая единый визуальный стиль.
Для компонентов, не использующих палитру MUI напрямую, можно
применять хук useMediaQuery для изменения стилей
вручную:
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const styles = {
container: {
backgroundColor: prefersDarkMode ? '#121212' : '#fff',
color: prefersDarkMode ? '#fff' : '#000',
},
};
Это позволяет расширять поддержку системной темы на любые элементы интерфейса, даже если они не являются стандартными компонентами MUI.
useMediaQuery('(prefers-color-scheme: dark)') для
определения системного режима.createTheme с разделением на
light и dark палитры.useMemo для оптимизации производительности
при динамическом изменении темы.localStorage для сохранения
пользовательских предпочтений.CssBaseline для согласованного применения
темы ко всему приложению.useMediaQuery
напрямую для управления стилями.Такой подход обеспечивает полную адаптивность приложения к системным настройкам, улучшает UX и минимизирует необходимость ручного управления цветовой схемой.