图标
使用 Material UI 图标的指南和建议。
Material UI 通过三种方式提供图标支持
- 通过导出为 React 组件(SVG 图标)的 Material 图标。
- 通过 SvgIcon 组件,一个用于自定义 SVG 图标的 React 包装器。
- 通过 Icon 组件,一个用于自定义字体图标的 React 包装器。
Material SVG 图标
Google 创建了超过 2,100 个官方 Material 图标,每个图标有五种不同的“主题”(见下文)。对于每个 SVG 图标,我们从 @mui/icons-material
包中导出相应的 React 组件。您可以搜索这些图标的完整列表。
安装
运行以下命令之一来安装它并将其保存到您的 package.json
依赖项中
npm install @mui/icons-material
这些组件使用 Material UI SvgIcon
组件来渲染每个图标的 SVG 路径,因此对 @mui/material
具有对等依赖。
如果您的项目中尚未使用 Material UI,您可以按照安装指南添加它。
用法
使用以下两个选项之一导入图标
选项 1
import AccessAlarmIcon from '@mui/icons-material/AccessAlarm'; import ThreeDRotation from '@mui/icons-material/ThreeDRotation';
选项 2
import { AccessAlarm, ThreeDRotation } from '@mui/icons-material';
对于 bundle 大小而言,选项 1 是最安全的,但一些开发者更喜欢选项 2。在使用第二种方法之前,请确保您遵循最小化 bundle 大小指南。
每个 Material 图标也都有一个“主题”:Filled(默认)、Outlined、Rounded、Two-tone 和 Sharp。要导入具有默认主题以外主题的图标组件,请将主题名称附加到图标名称。例如,具有以下主题的 @mui/icons-material/Delete
图标:
- Filled 主题(默认)导出为
@mui/icons-material/Delete
, - Outlined 主题导出为
@mui/icons-material/DeleteOutlined
, - Rounded 主题导出为
@mui/icons-material/DeleteRounded
, - Two-tone 主题导出为
@mui/icons-material/DeleteTwoTone
, - Sharp 主题导出为
@mui/icons-material/DeleteSharp
。
Filled
Outlined
Rounded
Two Tone
Sharp
边缘情况
SvgIcon
如果您需要自定义 SVG 图标(在 Material 图标中不可用),您可以使用 SvgIcon
包装器。此组件扩展了原生 <svg>
元素
- 它具有内置的可访问性。
- SVG 元素应缩放为 24x24px 视口,以便生成的图标可以直接使用,或作为子元素包含在其他使用图标的 Material UI 组件中。可以使用
viewBox
属性自定义此设置。要从原始图像继承viewBox
值,可以使用inheritViewBox
属性。 - 默认情况下,组件继承当前颜色。可选地,您可以使用
color
属性应用主题颜色之一。 - 它支持
<svg>
元素作为子元素,因此您可以直接将 SVG 复制并粘贴到SvgIcon
组件中。
组件属性
即使您的图标以 .svg
格式保存,您也可以使用 SvgIcon
包装器。svgr 具有加载器,用于导入 SVG 文件并将它们用作 React 组件。例如,使用 webpack
// webpack.config.js
{
test: /\.svg$/,
use: ['@svgr/webpack'],
}
// ---
import StarIcon from './star.svg';
<SvgIcon component={StarIcon} inheritViewBox />
也可以将其与“url-loader”或“file-loader”一起使用。这是 Create React App 使用的方法。
// webpack.config.js
{
test: /\.svg$/,
use: ['@svgr/webpack', 'url-loader'],
}
// ---
import { ReactComponent as StarIcon } from './star.svg';
<SvgIcon component={StarIcon} inheritViewBox />
createSvgIcon
createSvgIcon
实用程序组件用于创建 Material 图标。它可用于包装 <svg>
元素或作为子元素传递给 SvgIcon
组件的 SVG 路径。
const HomeIcon = createSvgIcon(
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />,
'Home',
);
// or with custom SVG
const PlusIcon = createSvgIcon(
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="h-6 w-6"
>
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
</svg>,
'Plus',
);
Font Awesome
如果您发现从 @fortawesome/react-fontawesome
使用 FontAwesomeIcon 时存在布局问题,您可以尝试将 Font Awesome SVG 数据直接传递给 SvgIcon。
以下是 FontAwesomeIcon
组件和包装的 SvgIcon
组件的比较。
FontAwesomeIcon 的 fullWidth
属性也可用于近似正确的尺寸,但它并不完美。
其他库
MDI
materialdesignicons.com 提供了超过 2,000 个图标。对于所需的图标,复制他们提供的 SVG path
,并将其用作 SvgIcon
组件的子元素,或与 createSvgIcon()
一起使用。
注意:mdi-material-ui 已经使用 SvgIcon
组件包装了这些 SVG 图标中的每一个,因此您无需自己进行操作。
Icon (字体图标)
Icon
组件将显示来自任何支持连字的字体图标的图标。作为先决条件,您必须包含一个,例如您项目中的 Material Icons 字体。要使用图标,只需使用 Icon
组件包装图标名称(字体连字),例如
import Icon from '@mui/material/Icon';
<Icon>star</Icon>;
默认情况下,Icon 将继承当前文本颜色。可选地,您可以使用主题颜色属性之一设置图标颜色:primary
、secondary
、action
、error
和 disabled
。
字体 Material 图标
Icon
默认情况下将为 Material Icons 字体(filled 变体)设置正确的基类名称。您所需要做的就是加载字体,例如,通过 Google Web Fonts
<link
rel="stylesheet"
href="https://fonts.googleapis.com/icon?family=Material+Icons"
/>
自定义字体
对于其他字体,您可以使用 baseClassName
属性自定义基线类名称。例如,您可以使用 Material Design 显示 two-tone 图标
import Icon from '@mui/material/Icon';
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Material+Icons+Two+Tone"
// Import the two tones MD variant ^^^^^^^^
/>;
全局基类名称
为每个组件用法修改 baseClassName
属性是重复的。您可以使用主题全局更改默认属性
const theme = createTheme({
components: {
MuiIcon: {
defaultProps: {
// Replace the `material-icons` default value.
baseClassName: 'material-icons-two-tone',
},
},
},
});
然后,您可以直接使用 two-tone 字体
<Icon>add_circle</Icon>
Font Awesome
Font Awesome 可以与 Icon
组件一起使用,如下所示
请注意,Font Awesome 图标的设计方式与 Material 图标不同(比较之前的两个演示)。fa 图标被裁剪以使用所有可用空间。您可以使用全局覆盖来调整此设置
const theme = createTheme({
components: {
MuiIcon: {
styleOverrides: {
root: {
// Match 24px = 3 * 2 + 1.125 * 16
boxSizing: 'content-box',
padding: 3,
fontSize: '1.125rem',
},
},
},
},
});
字体与 SVG:应使用哪种方法?
两种方法都可以正常工作,但是,在性能和渲染质量方面存在一些细微的差异。在可能的情况下,首选 SVG,因为它允许代码拆分,支持更多图标,并且渲染速度更快、质量更高。
有关更多详细信息,请查看 GitHub 为什么从字体图标迁移到 SVG 图标。
可访问性
图标可以传达各种有意义的信息,因此确保它们在适当的情况下可访问非常重要。您需要考虑两种用例
- 装饰性图标仅用于视觉或品牌强化。如果从页面中删除它们,用户仍然可以理解并能够使用您的页面。
- 语义图标是您用于传达含义的图标,而不仅仅是纯粹的装饰。这包括旁边没有文本的图标,这些图标用作交互式控件——按钮、表单元素、切换等。
装饰性图标
如果您的图标纯粹是装饰性的,那么您已经完成了!添加了 aria-hidden=true
属性,以便您的图标可以正确访问(不可见)。
语义图标
语义 SVG 图标
您应该包含具有有意义值的 titleAccess
属性。添加了 role="img"
属性和 <title>
元素,以便您的图标可以正确访问。
在可聚焦的交互式元素的情况下,例如当与图标按钮一起使用时,您可以使用 aria-label
属性
import IconButton from '@mui/material/IconButton';
import SvgIcon from '@mui/material/SvgIcon';
// ...
<IconButton aria-label="delete">
<SvgIcon>
<path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z" />
</SvgIcon>
</IconButton>;
语义字体图标
您需要提供仅对辅助技术可见的文本替代方案。
import Box from '@mui/material/Box';
import Icon from '@mui/material/Icon';
import { visuallyHidden } from '@mui/utils';
// ...
<Icon>add_circle</Icon>
<Box component="span" sx={visuallyHidden}>Create a user</Box>