Responsive значения в теме

MUI (Material-UI) предоставляет мощный механизм для работы с адаптивными стилями, позволяя создавать интерфейсы, которые корректно подстраиваются под различные размеры экранов. Основой для этого являются responsive значения, применяемые в теме через объект theme.

Система breakpoints

MUI использует систему breakpoints, определяющую ключевые размеры экранов:

const theme = createTheme({
  breakpoints: {
    values: {
      xs: 0,
      sm: 600,
      md: 900,
      lg: 1200,
      xl: 1536,
    },
  },
});

Значения xs, sm, md, lg, xl обозначают минимальную ширину экрана, начиная с которой будут применяться определённые стили. Breakpoints применяются с помощью:

  • up(key) — стили для экранов от указанного размера и выше.
  • down(key) — стили для экранов до указанного размера включительно.
  • between(start, end) — стили для диапазона экранов.
  • only(key) — стили только для конкретного брейкпоинта.

Пример использования:

const useStyles = makeStyles((theme) => ({
  container: {
    padding: theme.spacing(2),
    [theme.breakpoints.up('sm')]: {
      padding: theme.spacing(4),
    },
    [theme.breakpoints.up('md')]: {
      padding: theme.spacing(6),
    },
  },
}));

В этом примере padding увеличивается с ростом ширины экрана.


Responsive значения в свойствах темы

MUI позволяет задавать адаптивные значения напрямую в теме для свойств spacing, typography, palette и пользовательских кастомных свойств. Наиболее часто используются объекты с ключами брейкпоинтов:

const theme = createTheme({
  typography: {
    h1: {
      fontSize: {
        xs: '2rem',
        sm: '2.5rem',
        md: '3rem',
      },
      fontWeight: 500,
    },
  },
});

В этом примере размер заголовка h1 изменяется в зависимости от ширины экрана:

  • xs — мобильные устройства
  • sm — планшеты
  • md — десктоп

Это позволяет создавать динамическую типографику без написания сложных медиа-запросов вручную.


Использование responsiveFontSizes

Для автоматической адаптации всех размеров шрифтов в теме MUI предоставляет функцию responsiveFontSizes:

let theme = createTheme({
  typography: {
    h1: { fontSize: '2rem' },
    body1: { fontSize: '1rem' },
  },
});

theme = responsiveFontSizes(theme);

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


Массивы как альтернативный синтаксис

MUI также поддерживает использование массивов значений, которые соответствуют брейкпоинтам в порядке [xs, sm, md, lg, xl]:

const Box = styled('div')(({ theme }) => ({
  width: ['100%', '80%', '60%', '50%', '40%'],
}));

В этом примере:

  • 100% для xs
  • 80% для sm
  • 60% для md
  • 50% для lg
  • 40% для xl

Этот синтаксис особенно удобен для компонентов styled, когда нужно компактно задать адаптивные значения без прописывания длинных медиазапросов вручную.


Пользовательские responsive свойства

Можно создавать свои адаптивные значения в теме:

const theme = createTheme({
  custom: {
    cardPadding: {
      xs: 8,
      sm: 16,
      md: 24,
    },
  },
});

Затем использовать их в компонентах:

 theme.custom.cardPadding.md }} />

Для удобства можно комбинировать с функциями theme.breakpoints.up() или down() для динамического переключения между значениями в зависимости от ширины экрана.


Использование в sx и styled

Система responsive MUI полностью интегрирована с sx и styled API:

Преимущества такого подхода:

  • Нет необходимости писать CSS медиа-запросы вручную
  • Компактный и читаемый код
  • Полная интеграция с системой тем MUI

Для styled компонентов синтаксис аналогичен:

const StyledButton = styled(Button)(({ theme }) => ({
  fontSize: theme.typography.pxToRem(14),
  [theme.breakpoints.up('sm')]: {
    fontSize: theme.typography.pxToRem(16),
  },
  [theme.breakpoints.up('md')]: {
    fontSize: theme.typography.pxToRem(18),
  },
}));

Миксин theme.breakpoints

Для повторного использования responsive логики удобно создавать миксины:

const responsivePadding = (property, values) => (theme) => ({
  [theme.breakpoints.up('xs')]: { [property]: values.xs },
  [theme.breakpoints.up('sm')]: { [property]: values.sm },
  [theme.breakpoints.up('md')]: { [property]: values.md },
});

const Box = styled('div')(({ theme }) => ({
  ...responsivePadding('padding', { xs: 8, sm: 16, md: 24 }),
}));

Такой подход упрощает поддержку крупных проектов с многочисленными адаптивными стилями.