MUI предоставляет встроенную поддержку иконок через библиотеку
@mui/icons-material, однако в реальных проектах часто
возникает необходимость использовать свои, кастомные
SVG-иконки. Для этого MUI предлагает гибкие инструменты,
позволяющие интегрировать иконки без потери совместимости с компонентами
библиотеки, такими как Button, IconButton или
ListItemIcon.
Самый простой способ добавить кастомную иконку — использовать
компонент SvgIcon из @mui/material. Этот
компонент позволяет обернуть SVG-контент и преобразовать его в
полноценный компонент MUI.
import SvgIcon from '@mui/material/SvgIcon';
function HomeIcon(props) {
return (
<SvgIcon {...props}>
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</SvgIcon>
);
}
Ключевые моменты:
viewBox из исходного SVG автоматически
подхватывается SvgIcon, но его можно переопределить при
необходимости.props, переданные компоненту, автоматически
поддерживают стилизацию через sx или стандартные свойства
MUI (color, fontSize).SvgIcon позволяет сохранять совместимость
с компонентами MUI, например:import IconButton from '@mui/material/IconButton';
<IconButton color="primary">
<HomeIcon fontSize="large" />
</IconButton>
MUI предоставляет несколько способов управлять стилями кастомных иконок:
color: SvgIcon
поддерживает стандартные цвета MUI: primary,
secondary, action, error,
disabled, inherit.<HomeIcon color="secondary" />
fontSize: Можно
использовать предустановленные размеры: small,
medium, large, или указать кастомный размер
через sx.<HomeIcon fontSize="small" />
<HomeIcon sx={{ fontSize: 48 }} />
sx для полной кастомизации:
Позволяет задавать любые CSS-свойства:<HomeIcon sx={{ color: 'green', transform: 'rotate(45deg)' }} />
Для удобства лучше вынести все кастомные иконки в отдельный модуль,
например icons.js:
import SvgIcon from '@mui/material/SvgIcon';
export function HomeIcon(props) {
return (
<SvgIcon {...props}>
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</SvgIcon>
);
}
export function SettingsIcon(props) {
return (
<SvgIcon {...props}>
<path d="M19.43 12.98l1.77-1.03-1-1.73-1.77 1.03a6.947 6.947 0 0 0-1.69-0.98l-0.27-1.92h-2l-0.27 1.92c-0.62 0.21-1.2 0.52-1.69 0.98L5.8 10.22l-1 1.73 1.77 1.03c-0.05 0.33-0.08 0.66-0.08 1s0.03 0.67 0.08 1l-1.77 1.03 1 1.73 1.77-1.03c0.49 0.46 1.07 0.77 1.69 0.98l0.27 1.92h2l0.27-1.92c0.62-0.21 1.2-0.52 1.69-0.98l1.77 1.03 1-1.73-1.77-1.03c0.05-0.33 0.08-0.66 0.08-1s-0.03-0.67-0.08-1z"/>
</SvgIcon>
);
}
Теперь их легко импортировать в любом компоненте:
import { HomeIcon, SettingsIcon } from './icons';
<HomeIcon color="primary" />
<SettingsIcon sx={{ fontSize: 36, color: 'red' }} />
Кастомные иконки полностью совместимы с компонентами, которые ожидают иконку:
import Button from '@mui/material/Button';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
<Button startIcon={<HomeIcon />}>Главная</Button>
<List>
<ListItem>
<ListItemIcon>
<SettingsIcon />
</ListItemIcon>
<ListItemText primary="Настройки" />
</ListItem>
</List>
Это позволяет создать единый визуальный стиль приложения, не ограничиваясь библиотечными иконками.
Если SVG уже хранится как отдельный файл, его можно импортировать с
помощью @svgr/webpack (часто настроено по умолчанию в
Create React App) или обернуть вручную:
import { ReactComponent as LogoSVG } from './logo.svg';
import SvgIcon from '@mui/material/SvgIcon';
function LogoIcon(props) {
return (
<SvgIcon component={LogoSVG} viewBox="0 0 100 100" {...props} />
);
}
Преимущества такого подхода:
color, fontSize и
sx.svgo) для уменьшения размера бандла.memo для часто используемых
иконок, чтобы избежать лишних перерендеров:import { memo } from 'react';
const HomeIconMemo = memo(HomeIcon);
Хотите, я подготовлю ещё часть с динамическими иконками и анимацией на базе MUI? Это полезно для интерактивных кнопок и уведомлений.