Tranform SVG into React components
svgr
Transform SVG into React components.
npm install svgr
Example
Take an icon.svg:
<?xml version="1.0" encoding="UTF-8"?>
<svg width="48px" height="1px" viewBox="0 0 48 1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>Rectangle 5</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="19-Separator" transform="translate(-129.000000, -156.000000)" fill="#063855">
<g id="Controls/Settings" transform="translate(80.000000, 0.000000)">
<g id="Content" transform="translate(0.000000, 64.000000)">
<g id="Group" transform="translate(24.000000, 56.000000)">
<g id="Group-2">
<rect id="Rectangle-5" x="25" y="36" width="48" height="1"></rect>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
Run SVGR
svgr --no-semi --icon --replace-attr-value "#063855=currentColor" icon.svg
Output
import React from 'react'
const SvgComponent = props => (
<svg width="1em" height="1em" viewBox="0 0 48 1" {...props}>
<path d="M0 0h48v1H0z" fill="currentColor" fillRule="evenodd" />
</svg>
)
export default SvgComponent
Motivation
React supports SVG out of the box, it's simpler, easier and much more powerful
to have components instead of SVG files. Wrapped in a React component, your SVG
is inlined in the page and you can style it using CSS.
There are a lot of similar projects, but I wanted something more solid and
configurable. SVGR is based on h2x, a
powerful and configurable HTML transpiler. It uses AST (like
Babel) that gives a lot of power.
Command line usage
Usage: svgr [options] <file>
Options:
-V, --version output the version number
--ext <ext> specify a custom file extension (default: "js")
--icon use "1em" as width and height
--ids keep ids within the svg (svgo)
--jsx-bracket-same-line put the > of a multi-line JSX element at the end of the last line instead of being alone on the next line (prettier)
--keep-useless-defs keep elements of <defs> without id (svgo)
--native add react-native support with react-native-svg
--no-bracket-spacing print spaces between brackets in object literals (prettier)
--no-dimensions remove width and height from root SVG tag
--no-expand-props disable props expanding
--no-prettier disable Prettier
--no-semi remove semi-colons (prettier)
--no-svgo disable SVGO
--no-title remove title tag (svgo)
--no-view-box remove viewBox
-d, --out-dir <dirname> output files into a directory
-p, --precision <value> set the number of digits in the fractional part (svgo)
--ref add svgRef prop to svg
--replace-attr-value [old=new] replace an attribute value
--single-quote use single-quotes instead of double-quotes (prettier)
--tab-width <value> specify the number of spaces by indentation-level (prettier)
--template <file> specify a custom template to use
--trailing-comma <none|es5|all> print trailing commas wherever possible when multi-line (prettier)
--use-tabs indent lines with tabs instead of spaces (prettier)
-h, --help output usage information
Examples:
svgr --replace-attr-value "#fff=currentColor" icon.svg
Recipes
Transform a whole directory
A whole directory can be processed, all SVG files (matching .svg
or .SVG
)
are transformed into React components.
# Usage: svgr [-d out-dir] [src-dir]
$ svgr -d icons icons
icons/web/clock-icon.svg -> icons/web/ClockIcon.js
icons/web/wifi-icon.svg -> icons/web/WifiIcon.js
icons/spinner/cog-icon.svg -> icons/spinner/CogIcon.js
icons/spinner/spinner-icon.svg -> icons/spinner/SpinnerIcon.js
Use stdin
$ svgr < icons/web/wifi-icon.svg
Use stdin / stdout
$ svgr < icons/web/wifi-icon.svg > icons/web/WifiIcon.js
Transform icons
To create icons, two options are important:
--icon
: title is removed, viewBox is preserved and SVG inherits text size--replace-attr-value "#000000=currentColor"
: "#000000" is replaced by
"currentColor" and SVG inherits text color
$ svgr --icon --replace-attr-value "#000000=currentColor" my-icon.svg
Target React Native
It is possible to target React Native using react-native-svg.
$ svgr --native my-icon.svg
Use a specific template
You can use a specific template.
$ svgr --template path/to/template.js my-icon.svg
Example of template:
module.exports = (opts = {}) => {
let props = ''
if (opts.expandProps && opts.ref) {
props = '{svgRef, ...props}'
} else if (opts.expandProps) {
props = 'props'
} else if (opts.ref) {
props = '{svgRef}'
}
return (code, state) => `import React from 'react'
const ${state.componentName} = (${props}) => ${code}
export default ${state.componentName}`
}
Node API usage
SVGR can also be used programmatically:
import svgr from 'svgr'
const svgCode = `
<?xml version="1.0" encoding="UTF-8"?>
<svg width="88px" height="88px" viewBox="0 0 88 88" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
<title>Dismiss</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Blocks" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="square">
<g id="Dismiss" stroke="#063855" stroke-width="2">
<path d="M51,37 L37,51" id="Shape"></path>
<path d="M51,51 L37,37" id="Shape"></path>
</g>
</g>
</svg>
`
svgr(svgCode, { prettier: false, componentName: 'MyComponent' }).then(
jsCode => {
console.log(jsCode)
},
)
Webpack usage
SVGR has a Webpack loader, you can use it using following webpack.config.js
:
In your webpack.config.js
:
{
test: /\.svg$/,
use: ['svgr/webpack'],
}
In your code:
import Star from './star.svg'
const App = () => (
<div>
<Star />
</div>
)
Passing options
{
test: /\.svg$/,
use: [
{
loader: 'svgr/webpack',
options: {
native: true,
},
},
],
}
Using with url-loader
or file-loader
It is possible to use it with url-loader
or file-loader
.
In your webpack.config.js
:
{
test: /\.svg$/,
use: ['svgr/webpack', 'url-loader'],
}
In your code:
import starUrl, { ReactComponent as Star } from './star.svg'
const App = () => (
<div>
<img src={starUrl} alt="star" />
<Star />
</div>
)
Use your own Babel configuration
By default, svgr/webpack
includes a babel-loader
with optimized configuration. In some case you may want to apply a custom one (if you are using Preact for an example). You can turn off Babel transformation by specifying babel: false
in options.
// Example using preact
{
test: /\.svg$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['preact', 'env'],
},
},
{
loader: 'svgr/webpack',
options: { babel: false },
}
],
}
Handle SVG in CSS, Sass or Less
It is possible to detect the module that requires your SVG using Rule.issuer
in Webpack. Using it you can specify two different configurations for JavaScript and the rest of your files.
{
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
issuer: {
test: /\.jsx?$/
},
use: ['babel-loader', 'svgr/webpack', 'url-loader']
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url-loader'
},
}
Options
SVGR ships with a handful of customizable options, usable in both the CLI and
API.
File extension
Specify a custom extension for generated files.
Default | CLI Override | API Override |
---|---|---|
"js" |
--ext |
ext: <string> |
Icon
Replace SVG "width" and "height" value by "1em" in order to make SVG size
inherits from text size. Also remove title.
Default | CLI Override | API Override |
---|---|---|
false |
--icon |
icon: <bool> |
Ids
Setting this to true
will keep ids. It can be useful to target specific ids
using CSS or third party library (eg:
react-mutate-icon).
Default | CLI Override | API Override |
---|---|---|
false |
--ids |
ids: <bool> |
JSX Brackets
Put the >
of a multi-line JSX element at the end of the last line instead of
being alone on the next line (does not apply to self closing elements). See
Prettier.
Default | CLI Override | API Override |
---|---|---|
false |
--jsx-bracket-same-line |
jsxBracketSameLine: <bool> |
Useless Defs
Keep elements of <defs>
without id
. It also keep unused symbols. See
SVGO removeUselessDefs
plugin.
Default | CLI Override | API Override |
---|---|---|
false |
--keep-useless-defs |
keepUselessDefs: <bool> |
Native
Modify all SVG nodes with uppercase and use a specific template with
react-native-svg imports. All unsupported nodes will be removed.
Default | CLI Override | API Override |
---|---|---|
false |
--native |
native: <bool> |
Bracket Spacing
Print spaces between brackets in object literals. See
Prettier.
Default | CLI Override | API Override |
---|---|---|
true |
--no-bracket-spacing |
bracketSpacing: <bool> |
Dimensions
Remove width and height from root SVG tag.
Default | CLI Override | API Override |
---|---|---|
false |
--no-dimensions |
dimensions: <bool> |
Expand props
All properties given to component will be forwarded on SVG tag.
Default | CLI Override | API Override |
---|---|---|
true |
--no-expand-props |
expandProps: <bool> |
Prettier
Use Prettier to format JavaScript code
output.
Default | CLI Override | API Override |
---|---|---|
true |
--no-prettier |
prettier: <bool> |
Semicolons
Print semicolons at the ends of statements. See
Prettier.
Default | CLI Override | API Override |
---|---|---|
true |
--no-semi |
semi: <bool> |
SVGO
Use SVGO to optimize SVG code before
transforming it into a component.
Default | CLI Override | API Override |
---|---|---|
true |
--no-svgo |
svgo: <bool> |
Title
Setting this to false
will remove the title from SVG. See
SVGO removeTitle
plugin.
Default | CLI Override | API Override |
---|---|---|
true |
--no-title |
title: <bool> |
ViewBox
Setting this to false
will remove the viewBox property.
Default | CLI Override | API Override |
---|---|---|
true |
--no-view-box |
viewBox: <bool> |
Ref
Setting this to true
will allow you to hook into the ref of the svg components that are created by exposing a svgRef
prop
Default | CLI Override | API Override |
---|---|---|
false |
--ref |
ref: <bool> |
Replace attribute value
Replace an attribute value by an other. The main usage of this option is to
change an icon color to "currentColor" in order to inherit from text color.
Default | CLI Override | API Override |
---|---|---|
[] |
--replace-attr-value <old=new> |
replaceAttrValues: <string[[old, new]]> |
Quotes
Use single quotes instead of double quotes. See
Prettier.
Default | CLI Override | API Override |
---|---|---|
false |
--single-quote |
singleQuote: <bool> |
Tab Width
Specify the number of spaces per indentation-level. See
Prettier.
Default | CLI Override | API Override |
---|---|---|
2 |
--tab-width <int> |
tabWidth: <int> |
Template
Specify a template file (CLI) or a template function (API) to use. For an
example of template, see the default one.
Default | CLI Override | API Override |
---|---|---|
wrapIntoComponent |
--template |
template: <func> |
Trailing Commas
Print trailing commas wherever possible when multi-line. See
Prettier.
Default | CLI Override | API Override |
---|---|---|
"none" |
--trailing-comma <none|es5|all> |
trailingComma: "<none|es5|all>" |
Tabs
Indent lines with tabs instead of spaces. See
Prettier.
Default | CLI Override | API Override |
---|---|---|
false |
--use-tabs |
useTabs: <bool> |
Output Directory
Output files into a directory.
Default | CLI Override | API Override |
---|---|---|
undefined |
--out-dir <dirname> |
outDir: <dirname> |
Precision
Set number of digits in the fractional part. See
SVGO.
Default | CLI Override | API Override |
---|---|---|
3 |
--precision <int> |
precision: <int> |