Guidance and suggestions for using icons with MaterialĀ UI.
MaterialĀ UI provides icon support in three ways:
Google has created over 2,100 official Material icons, each in five different āthemesā (see below).
For each SVG icon, we export the respective React component from the @mui/icons-material
package.
You can search the full list of these icons.
Run one of the following commands to install it and save it to your package.json
dependencies:
pnpm add @mui/icons-material
yarn add @mui/icons-material
These components use the MaterialĀ UI SvgIcon
component to render the SVG path for each icon, and so have a peer-dependency on @mui/material
.
If you arenāt already using MaterialĀ UI in your project, you can add it following the installation guide.
Import icons using one of these two options:
Option 1:
import AccessAlarmIcon from '@mui/icons-material/AccessAlarm';
import ThreeDRotation from '@mui/icons-material/ThreeDRotation';
Option 2:
import { AccessAlarm, ThreeDRotation } from '@mui/icons-material';
The safest for bundle size is Option 1, but some developers prefer Option 2. Make sure you follow the minimizing bundle size guide before using the second approach.
Each Material icon also has a āthemeā: Filled (default), Outlined, Rounded, Two-tone, and Sharp. To import the icon component with a theme other than the default, append the theme name to the icon name. For example @mui/icons-material/Delete
icon with:
@mui/icons-material/Delete
,@mui/icons-material/DeleteOutlined
,@mui/icons-material/DeleteRounded
,@mui/icons-material/DeleteTwoTone
,@mui/icons-material/DeleteSharp
.The Material Design guidelines name the icons using āsnake_caseā naming (for example
delete_forever
,add_a_photo
), while@mui/icons-material
exports the respective icons using āPascalCaseā naming (for exampleDeleteForever
,AddAPhoto
). There are three exceptions to this naming rule:3d_rotation
exported asThreeDRotation
,4k
exported asFourK
, and360
exported asThreeSixty
.
{{ādemoā: āSvgMaterialIcons.jsā}}
For testing purposes, each icon exposed from @mui/icons-material
has a data-testid
attribute with the name of the icon. For instance:
import DeleteIcon from '@mui/icons-material/Delete';
has the following attribute once mounted:
<svg data-testid="DeleteIcon"></svg>
If you need a custom SVG icon (not available in the Material Icons) you can use the SvgIcon
wrapper.
This component extends the native <svg>
element:
viewBox
attribute.
To inherit the viewBox
value from the original image, the inheritViewBox
prop can be used.color
prop.<svg>
element as a child so you can copy and paste your SVG directly to SvgIcon
component.{{ādemoā: āSvgIconChildren.jsā}}
{{ādemoā: āSvgIconsColor.jsā}}
{{ādemoā: āSvgIconsSize.jsā}}
You can use the SvgIcon
wrapper even if your icons are saved in the .svg
format.
svgr has loaders to import SVG files and use them as React components. For example, with webpack:
// webpack.config.js
{
test: /\.svg$/,
use: ['@svgr/webpack'],
}
// ---
import StarIcon from './star.svg';
<SvgIcon component={StarIcon} inheritViewBox />
Itās also possible to use it with āurl-loaderā or āfile-loaderā. This is the approach used by Create React App.
// webpack.config.js
{
test: /\.svg$/,
use: ['@svgr/webpack', 'url-loader'],
}
// ---
import { ReactComponent as StarIcon } from './star.svg';
<SvgIcon component={StarIcon} inheritViewBox />
The createSvgIcon
utility component is used to create the Material Icons. It can be used to wrap an <svg>
element or an SVG path which is passed as a child to the SvgIcon
component.
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',
);
{{ādemoā: āCreateSvgIcon.jsā}}
If you find that there are layout issues when using FontAwesomeIcon from @fortawesome/react-fontawesome
, you can try passing the Font Awesome SVG data directly to SvgIcon.
Below is a comparison of the FontAwesomeIcon
component and a wrapped SvgIcon
component.
{{ādemoā: āFontAwesomeSvgIconDemo.jsā}}
FontAwesomeIconās fullWidth
prop can also be used to approximate the correct dimensions, but it isnāt perfect.
materialdesignicons.com provides over 2,000 icons.
For the wanted icon, copy the SVG path
they provide, and use it as the child of the SvgIcon
component, or with createSvgIcon()
.
Note: mdi-material-ui has already wrapped each of these SVG icons with the SvgIcon
component, so you donāt have to do it yourself.
The Icon
component will display an icon from any icon font that supports ligatures.
As a prerequisite, you must include one, such as the
Material Icons font in your project.
To use an icon simply wrap the icon name (font ligature) with the Icon
component,
for example:
import Icon from '@mui/material/Icon';
<Icon>star</Icon>;
By default, an Icon will inherit the current text color.
Optionally, you can set the icon color using one of the theme color properties: primary
, secondary
, action
, error
& disabled
.
Icon
will by default set the correct base class name for the Material Icons font (filled variant).
All you need to do is load the font, for instance, via Google Web Fonts:
<link
rel="stylesheet"
href="https://fonts.googleapis.com/icon?family=Material+Icons"
/>
{{ādemoā: āIcons.jsā}}
For other fonts, you can customize the baseline class name using the baseClassName
prop.
For instance, you can display two-tone icons with Material Design:
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 ^^^^^^^^
/>;
{{ādemoā: āTwoToneIcons.jsā}}
Modifying the baseClassName
prop for each component usage is repetitive.
You can change the default prop globally with the theme
const theme = createTheme({
components: {
MuiIcon: {
defaultProps: {
// Replace the `material-icons` default value.
baseClassName: 'material-icons-two-tone',
},
},
},
});
Then, you can use the two-tone font directly:
<Icon>add_circle</Icon>
Font Awesome can be used with the Icon
component as follows:
{{ādemoā: āFontAwesomeIcon.jsā}}
Note that the Font Awesome icons werenāt designed like the Material Icons (compare the two previous demos). The fa icons are cropped to use all the space available. You can adjust for this with a global override:
const theme = createTheme({
components: {
MuiIcon: {
styleOverrides: {
root: {
// Match 24px = 3 * 2 + 1.125 * 16
boxSizing: 'content-box',
padding: 3,
fontSize: '1.125rem',
},
},
},
},
});
{{ādemoā: āFontAwesomeIconSize.jsā}}
Both approaches work fine, however, there are some subtle differences, especially in terms of performance and rendering quality. Whenever possible SVG is preferred as it allows code splitting, supports more icons, and renders faster and better.
For more details, take a look at why GitHub migrated from font icons to SVG icons.
Icons can convey all sorts of meaningful information, so itās important to ensure they are accessible where appropriate. There are two use cases youāll want to consider:
If your icons are purely decorative, youāre already done!
The aria-hidden=true
attribute is added so that your icons are properly accessible (invisible).
You should include the titleAccess
prop with a meaningful value.
The role="img"
attribute and the <title>
element are added so that your icons are correctly accessible.
In the case of focusable interactive elements, for example when used with an icon button, you can use the aria-label
prop:
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>;
You need to provide a text alternative that is only visible to assistive technologies.
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>