I've got an SVG file and I want to make an SvgIcon component out of it, how should I do that?
In the documentation, all the examples use either predefined Material Icons or a strange notation of <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" /> which I have no idea what it is!
10 Answers
1. Using <Icon/> component and an <img/> element
To use a SVG file as an icon, I used the <Icon/> component with an <img/> element inside, setting the height: 100% to the img element and textAlign: center to the root class of the <Icon/> component did the trick:
JSX:
import Icon from '@material-ui/core/Icon';
import { makeStyles } from '@material-ui/styles';
...
<Icon classes={{root: classes.iconRoot}}> <img className={classes.imageIcon} src="/graphics/firebase-logo.svg"/>
</Icon>Styles:
const useStyles = makeStyles({ imageIcon: { height: '100%' }, iconRoot: { textAlign: 'center' }
});Result:
UPDATE
As Lorenz Haase mentions in the comments, there is a slighly cuttting of the SVG at the bottom, which it can be fixed if we use flexbox and inherit width and height:
const useStyles = makeStyles({ imageIcon: { display: 'flex', height: 'inherit', width: 'inherit' }
});2. Using <SvgIcon/> component and @svgr/webpack webpack loader
According to the official MUI documentation, we can use <SvgIcon/> component props and have a @svgr/webpack loader to load .svg files using ESM imports.
Component prop
You can use the
SvgIconwrapper even if your icons are saved in the.svgformat. 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} viewBox="0 0 600 476.6" />It's also possible to use it with "url-loader" or "file-loader". It's 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} viewBox="0 0 600 476.6" /> 7 <path /> is an SVG path, i.e. the internal bits of the SVG. the SvgIcon component really should be able to take a path, but it doesn't :(
instead you can create a component like
with your svg source in place of the path. (I recommend minifying it a bit using )
You can import SVGs directly as React components and use them in <SvgIcon>:
import React from "react";
import { ReactComponent as Logo } from "./logo.svg";
import SvgIcon from "@material-ui/core/SvgIcon";
const App = () => ( <SvgIcon> <Logo /> </SvgIcon>
);
export default App;See also:
Unfortunately React seems not able to render all kind of SVGs (e.g. modified with Inkscape, Illustrator) yet. But at least the default logo.svg inside a create-react-app project works.
To obtain the path for SvgIcon, open svg file with the text editor and copy the corresponding path expression.
The solution that worked for me is the following
import React from 'react'; import pure from 'recompose/pure'; import {SvgIcon} from '@material-ui/core'; let smile = (props) => ( <SvgIcon {...props} >
<path d="M256,32C132.281,32,32,132.281,32,256s100.281,224,224,224s224-100.281,224-224S379.719,32,256,32z M256,448
c-105.875,0-192-86.125-192-192S150.125,64,256,64s192,86.125,192,192S361.875,448,256,448z M160,192c0-26.5,14.313-48,32-48
s32,21.5,32,48c0,26.531-14.313,48-32,48S160,218.531,160,192z M288,192c0-26.5,14.313-48,32-48s32,21.5,32,48
c0,26.531-14.313,48-32,48S288,218.531,288,192z M384,288c-16.594,56.875-68.75,96-128,96c-59.266,0-111.406-39.125-128-96"/> </SvgIcon> ); smile = pure(smile); smile.displayName = 'smile'; smile.muiName = 'SvgIcon'; export default smile;Check this example of material ui icon
1The SvgIcon is not meant for this purpose. More on this @ Github.
You are probably looking for this startIcon={<img src={google}></img>}
import google from "../../Assets/img/google.svg";
import GitHubIcon from "@material-ui/icons/GitHub";
const useStyles = makeStyles((theme) => ({ root: { display: "flex", flexDirection: "column", margin: theme.spacing(1), }, button: { margin: "0.5rem", }, googleStyle: { fillColor: theme.palette.primary.main, }, }));
export default function ContainedButtons() { const classes = useStyles(); return ( <div> <Button variant="contained" color="secondary" className={classes.button} startIcon={<img src={google}></img>} > Login With Google </Button> <Button variant="contained" color="secondary" className={classes.button} startIcon={<GitHubIcon />} > Login with GitHub </Button>
</div>
);
} 1 If making more than one icon, you may not want to repeat all the boilerplate in the example referenced in the accepted answer. You can use a wrapper component generator like:
const wrapSvgPath = (path, viewBox='0 0 24 24') => (props) => ( <SvgIcon {...props} viewBox={viewBox}>{path}</SvgIcon>
)used like:
const facebookPath = (<path d="M17,2V2H17V6H15C14.31,6 14,6.81 14,7.5V10H14L17,10V14H14V22H10V14H7V10H10V6A4,4 0 0,1 14,2H17Z" />
)
export const FacebookIcon = wrapSvgPath(facebookPath) 0 import SvgIcon from '@material-ui/core/SvgIcon'
import Register from "./../../media/register.svg"
import React from 'react';
const getSvgIconMaterial = (Icon: string, props?: any) => { return ( <SvgIcon component="object"> <embed type="image/svg+xml" src={Icon} style={{ height: "100%" }} /> </SvgIcon> );
};use like this
<>{getSvgIconMaterial(Register)}</>Probably not perfect but works nicely. Maybe add a small padding/margin.
Open your svg file in a editor (example: vscode). You will see a file structure of something similar like this ->
<svg width="27" height="28" viewBox="0 0 27 28" fill="none" xmlns="">
<path d="M5.91942 27.5138L6.15827 26.984L8.69599 21.1562H8.68852L13.5027 10.3812L18.3542 21.1562H18.3467L21.1083 27.5138H26.2509L15.8687 4.72523L13.5698 0L0.933594 27.5138H5.91942Z" fill="#A7A9AC"/>
</svg>Then go to your react components, replace path with your own path. This should work. Add styles for custom change of design.
import svg file to your react application folder . Then in the file / component in which you want to use the svg icon use
import { ReactComponent as MyIcon } from '../svgiconfolder/myicon.svg'
export function MyCompnent(){return <MyIcon />}if you want to change colour use
import {ReactComponent as MyIcon} from '../svgiconfolder/myicon.svg'
export function MyCompnent(){return <MyIcon fill="#00000"/>}//use the color code in fill or if there is any color attribute in svg file try to use that