MUI (Material-UI) предоставляет мощный механизм работы с темами,
который позволяет управлять внешним видом компонентов приложения
централизованно. Основным инструментом является объект
theme, создаваемый с помощью функции
createTheme. Важнейшей особенностью является возможность
переключения между различными темами, например, светлой и тёмной.
Пример создания базовой темы:
import { createTheme } from '@mui/material/styles';
const lightTheme = createTheme({
palette: {
mode: 'light',
primary: {
main: '#1976d2',
},
secondary: {
main: '#dc004e',
},
},
});
const darkTheme = createTheme({
palette: {
mode: 'dark',
primary: {
main: '#90caf9',
},
secondary: {
main: '#f48fb1',
},
},
});
ThemeProvider для внедрения темыДля применения темы в приложении используется компонент ThemeProvider из MUI. Он оборачивает корневой компонент или любую часть дерева компонентов, передавая созданную тему через контекст.
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import App from './App';
function Root({ theme }) {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<App />
</ThemeProvider>
);
}
CssBaseline автоматически синхронизирует базовые стили с текущей темой, включая фоновый цвет, цвет текста и типографику.
Для динамического переключения тем применяют React
state. Обычно создаётся состояние, которое хранит текущий режим
(light или dark) и изменяет его по событию
пользователя, например, клику на кнопку.
import { useState } from 'react';
import { ThemeProvider, createTheme, Button } from '@mui/material';
import CssBaseline from '@mui/material/CssBaseline';
import App from './App';
function Root() {
const [mode, setMode] = useState('light');
const toggleTheme = () => {
setMode(prevMode => (prevMode === 'light' ? 'dark' : 'light'));
};
const theme = createTheme({
palette: {
mode: mode,
primary: {
main: mode === 'light' ? '#1976d2' : '#90caf9',
},
secondary: {
main: mode === 'light' ? '#dc004e' : '#f48fb1',
},
},
});
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Button onCl ick={toggleTheme}>
Переключить тему
</Button>
<App />
</ThemeProvider>
);
}
MUI позволяет не только менять режим
(light/dark), но и тонко настраивать цвета
отдельных компонентов через palette и
components в объекте темы.
const customTheme = createTheme({
palette: {
mode: 'dark',
primary: {
main: '#ff9800',
},
background: {
default: '#121212',
paper: '#1d1d1d',
},
},
components: {
MuiButton: {
styleOverrides: {
root: {
borderRadius: 12,
textTransform: 'none',
},
},
},
},
});
Важно: переопределения в components
работают для всех компонентов данного типа в пределах темы.
Создание новой темы на каждый рендер может быть дорогим. Для оптимизации применяют useMemo, чтобы объект темы пересоздавался только при изменении режима.
import { useMemo } from 'react';
const theme = useMemo(() => createTheme({
palette: { mode },
}), [mode]);
Это предотвращает ненужные перерасчёты стилей и повторные рендеры дочерних компонентов.
Для сохранения выбранной темы между сессиями часто используют
localStorage:
useEffect(() => {
const savedMode = localStorage.getItem('themeMode');
if (savedMode) setMode(savedMode);
}, []);
useEffect(() => {
localStorage.setItem('themeMode', mode);
}, [mode]);
Таким образом, приложение автоматически применяет последнюю выбранную тему при повторном открытии.
MUI позволяет учитывать системный режим через
useMediaQuery:
import { useMediaQuery } from '@mui/material';
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const [mode, setMode] = useState(prefersDarkMode ? 'dark' : 'light');
Это обеспечивает синхронизацию темы приложения с настройками ОС пользователя.
Переключение тем может включать не только цвета, но и размеры, шрифты
и отступы через typography и spacing:
const theme = createTheme({
palette: { mode },
typography: {
h1: { fontSize: mode === 'light' ? '2rem' : '2.2rem' },
},
spacing: factor => factor * (mode === 'light' ? 8 : 10),
});
Это позволяет создавать полностью адаптивный интерфейс, подстраивающийся под контекст темы.
Большинство компонентов MUI автоматически реагируют на изменение
темы, включая Button, AppBar,
Paper, TextField. Компоненты наследуют цвета,
отступы и типографику из текущей темы. Для случаев, когда требуется
более детальное управление стилями, используют sx и
styled:
import { styled } from '@mui/material/styles';
import Button from '@mui/material/Button';
const CustomButton = styled(Button)(({ theme }) => ({
backgroundColor: theme.palette.primary.main,
color: theme.palette.getContrastText(theme.palette.primary.main),
'&:hover': {
backgroundColor: theme.palette.primary.dark,
},
}));
Это позволяет создавать компоненты, полностью интегрированные с системой тем MUI.