Material-UI 图标系统 #
概述 #
MUI 提供了完整的图标解决方案,包括官方的 Material Icons 和自定义图标支持。
text
图标系统
│
├── @mui/icons-material Material Icons(2000+)
├── SvgIcon SVG 图标组件
├── Icon Font 图标组件
└── 自定义图标 自定义 SVG 图标
Material Icons #
安装 #
bash
npm install @mui/icons-material
基础用法 #
jsx
import { Delete, Add, Home, Settings } from '@mui/icons-material';
<Delete />
<Add />
<Home />
<Settings />
图标颜色 #
jsx
import { pink, green } from '@mui/material/colors';
<Stack direction="row" spacing={2}>
<Delete color="primary" />
<Delete color="secondary" />
<Delete color="error" />
<Delete color="warning" />
<Delete color="success" />
<Delete color="info" />
<Delete sx={{ color: pink[500] }} />
<Delete sx={{ color: green[500] }} />
</Stack>
图标尺寸 #
jsx
<Stack direction="row" spacing={2} alignItems="center">
<Delete fontSize="small" />
<Delete fontSize="medium" />
<Delete fontSize="large" />
<Delete sx={{ fontSize: 40 }} />
</Stack>
配合按钮使用 #
jsx
import { Button, IconButton } from '@mui/material';
import { Delete as DeleteIcon, Send as SendIcon, Add as AddIcon } from '@mui/icons-material';
<Stack spacing={2} direction="row">
<Button variant="contained" startIcon={<AddIcon />}>
添加
</Button>
<Button variant="contained" endIcon={<SendIcon />}>
发送
</Button>
<IconButton aria-label="delete">
<DeleteIcon />
</IconButton>
</Stack>
配合输入框使用 #
jsx
import { TextField, InputAdornment } from '@mui/material';
import { AccountCircle, Lock, Search } from '@mui/icons-material';
<Stack spacing={2}>
<TextField
label="搜索"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Search />
</InputAdornment>
),
}}
/>
<TextField
label="用户名"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<AccountCircle />
</InputAdornment>
),
}}
/>
<TextField
label="密码"
type="password"
InputProps={{
endAdornment: (
<InputAdornment position="end">
<Lock />
</InputAdornment>
),
}}
/>
</Stack>
SvgIcon 组件 #
SvgIcon 是所有图标的基础组件,可以用于包装自定义 SVG。
基础用法 #
jsx
import { SvgIcon } from '@mui/material';
function HomeIcon(props) {
return (
<SvgIcon {...props}>
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
</SvgIcon>
);
}
<HomeIcon />
<HomeIcon color="primary" />
<HomeIcon color="secondary" />
使用 SVG 路径 #
jsx
const path = 'M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z';
<SvgIcon>
<path d={path} />
</SvgIcon>
从 SVG 文件导入 #
jsx
import { ReactComponent as Logo } from './logo.svg';
<SvgIcon component={Logo} viewBox="0 0 24 24" />
自定义图标 #
创建图标组件 #
jsx
import { SvgIcon } from '@mui/material';
export function CustomIcon(props) {
return (
<SvgIcon {...props}>
<circle cx="12" cy="12" r="10" />
<path d="M8 12l2 2 4-4" stroke="white" strokeWidth="2" fill="none" />
</SvgIcon>
);
}
使用 Lucide Icons #
jsx
import { SvgIcon } from '@mui/material';
import { Home, User, Settings } from 'lucide-react';
function LucideIcon({ icon: Icon, ...props }) {
return (
<SvgIcon component={Icon} {...props} />
);
}
<LucideIcon icon={Home} />
<LucideIcon icon={User} />
<LucideIcon icon={Settings} />
使用 React Icons #
jsx
import { FaReact, FaVuejs, FaAngular } from 'react-icons/fa';
import { SvgIcon } from '@mui/material';
<SvgIcon component={FaReact} />
<SvgIcon component={FaVuejs} />
<SvgIcon component={FaAngular} />
Icon 组件(Font 图标) #
基础用法 #
jsx
import { Icon } from '@mui/material';
<Icon>star</Icon>
<Icon>favorite</Icon>
<Icon>settings</Icon>
配合 Material Icons 字体 #
jsx
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Icons"
/>
<Icon>home</Icon>
<Icon color="primary">star</Icon>
<Icon fontSize="large">favorite</Icon>
不同图标字体 #
jsx
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Icons+Outlined"
/>
<Icon baseClassName="material-icons-outlined">star</Icon>
图标库分类 #
常用图标 #
| 类别 | 图标示例 |
|---|---|
| 导航 | Home, Menu, ArrowBack, ArrowForward |
| 操作 | Add, Edit, Delete, Save, Cancel |
| 通信 | Mail, Phone, Chat, Send |
| 文件 | Folder, File, Download, Upload |
| 媒体 | Play, Pause, VolumeUp, VolumeOff |
| 社交 | Share, Favorite, ThumbUp, Comment |
| 状态 | Check, Close, Warning, Error |
搜索图标 #
jsx
import { Search as SearchIcon } from '@mui/icons-material';
<TextField
placeholder="搜索图标..."
InputProps={{
startAdornment: <SearchIcon />,
}}
/>
图标最佳实践 #
语义化使用 #
jsx
<IconButton aria-label="删除项目">
<DeleteIcon />
</IconButton>
<Button startIcon={<AddIcon />}>添加项目</Button>
一致的尺寸 #
jsx
const iconSize = {
small: 20,
medium: 24,
large: 32,
};
<DeleteIcon sx={{ fontSize: iconSize.small }} />
<DeleteIcon sx={{ fontSize: iconSize.medium }} />
<DeleteIcon sx={{ fontSize: iconSize.large }} />
图标按钮组 #
jsx
<IconButtonGroup>
<IconButton aria-label="加粗">
<FormatBoldIcon />
</IconButton>
<IconButton aria-label="斜体">
<FormatItalicIcon />
</IconButton>
<IconButton aria-label="下划线">
<FormatUnderlinedIcon />
</IconButton>
</IconButtonGroup>
图标列表 #
jsx
<List>
<ListItem>
<ListItemIcon>
<HomeIcon />
</ListItemIcon>
<ListItemText primary="首页" />
</ListItem>
<ListItem>
<ListItemIcon>
<SettingsIcon />
</ListItemIcon>
<ListItemText primary="设置" />
</ListItem>
<ListItem>
<ListItemIcon>
<LogoutIcon />
</ListItemIcon>
<ListItemText primary="退出" />
</ListItem>
</List>
图标动画 #
旋转动画 #
jsx
<RefreshIcon
sx={{
animation: 'spin 1s linear infinite',
'@keyframes spin': {
'0%': { transform: 'rotate(0deg)' },
'100%': { transform: 'rotate(360deg)' },
},
}}
/>
脉冲动画 #
jsx
<FavoriteIcon
sx={{
animation: 'pulse 1s ease-in-out infinite',
'@keyframes pulse': {
'0%': { transform: 'scale(1)' },
'50%': { transform: 'scale(1.2)' },
'100%': { transform: 'scale(1)' },
},
}}
/>
过渡动画 #
jsx
<IconButton
sx={{
'&:hover svg': {
transform: 'rotate(90deg)',
},
'& svg': {
transition: 'transform 0.3s',
},
}}
>
<SettingsIcon />
</IconButton>
实战示例:图标选择器 #
jsx
import { useState } from 'react';
import {
Grid,
Paper,
IconButton,
TextField,
InputAdornment,
Typography,
} from '@mui/material';
import * as Icons from '@mui/icons-material';
function IconPicker({ value, onChange }) {
const [search, setSearch] = useState('');
const iconNames = Object.keys(Icons).filter(
(name) => name.toLowerCase().includes(search.toLowerCase())
);
return (
<Paper sx={{ p: 2, maxWidth: 400 }}>
<TextField
fullWidth
placeholder="搜索图标..."
value={search}
onChange={(e) => setSearch(e.target.value)}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Icons.Search />
</InputAdornment>
),
}}
sx={{ mb: 2 }}
/>
<Grid container spacing={1} sx={{ maxHeight: 300, overflow: 'auto' }}>
{iconNames.slice(0, 100).map((name) => {
const Icon = Icons[name];
return (
<Grid item key={name}>
<IconButton
onClick={() => onChange(name)}
color={value === name ? 'primary' : 'default'}
>
<Icon />
</IconButton>
</Grid>
);
})}
</Grid>
</Paper>
);
}
下一步 #
继续学习 自定义组件,了解如何创建可复用的自定义组件!
最后更新:2026-03-28