Tranform 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
-d, --out-dir <dirname> output files into a directory
--no-svgo disable SVGO
--no-prettier disable Prettier
--template <file> specify a custom template to use
--no-expand-props disable props expanding
--icon use "1em" as width and height
--replace-attr-value [old=new] replace an attribute value
-p, --precision <value> set the number of digits in the fractional part (svgo)
--no-title remove title tag (svgo)
--tab-width specify the number of spaces by indentation-level (prettier)
--use-tabs indent lines with tabs instead of spaces (prettier)
--no-semi remove semi-colons (prettier)
--single-quote use single-quotes instead of double-quotes (prettier)
--trailing-comma <none|es5|all> print trailing commas wherever possible when multi-line (prettier)
--no-bracket-spacing print spaces between brackets in object literals (prettier)
--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)
-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.
$ 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 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
Use a specific template
You can use a specific template, for an example of template, see the default one.
$ svgr --template path/to/template.js my-icon.svg
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 }).then(jsCode => {
console.log(jsCode)
})
Webpack usage
SVGR has a Webpack loader, you can use it using following webpack.config.js
:
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
use: ['babel-loader', 'svgr/lib/webpack']
}
]
}
}
It is also possible to specify options:
module.exports = {
module: {
rules: [
{
test: /\.svg$/,
use: [
'babel-loader',
{
loader: 'svgr/lib/webpack',
options: {
svgo: false
}
},
]
}
]
}
}
Options
SVGR ships with a handful of customizable options, usable in both the CLI and API.
SVGO
Use SVGO to optimize SVG code before transforming it into a component.
Default | CLI Override | API Override |
---|---|---|
true |
--no-svgo |
svgo: <bool> |
Prettier
Use Prettier to format JavaScript code output.
Default | CLI Override | API Override |
---|---|---|
true |
--no-prettier |
prettier: <bool> |
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> |
Expand props
All properties given to component will be forwarded on SVG tag.
Default | CLI Override | API Override |
---|---|---|
true |
--no-expand-props |
expandProps: <bool> |
Icon
Remove title and replace SVG "width" and "height" value by "1em" (SVG size inherits from text size).
Default | CLI Override | API Override |
---|---|---|
false |
--icon |
icon: <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[]> |
Precision
Set number of digits in the fractional part. See SVGO.
Default | CLI Override | API Override |
---|---|---|
3 |
--precision <int> |
precision: <int> |
Title
Remove the title from SVG. See SVGO removeTitle
plugin.
Default | CLI Override | API Override |
---|---|---|
true |
--no-title |
title: <bool> |
Tab Width
Specify the number of spaces per indentation-level. See Prettier.
Default | CLI Override | API Override |
---|---|---|
2 |
--tab-width <int> |
tabWidth: <int> |
Tabs
Indent lines with tabs instead of spaces. See Prettier.
Default | CLI Override | API Override |
---|---|---|
false |
--use-tabs |
useTabs: <bool> |
Semicolons
Print semicolons at the ends of statements. See Prettier.
Default | CLI Override | API Override |
---|---|---|
true |
--no-semi |
semi: <bool> |
Quotes
Use single quotes instead of double quotes. See Prettier.
Default | CLI Override | API Override |
---|---|---|
false |
--single-quote |
singleQuote: <bool> |
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>" |
Bracket Spacing
Print spaces between brackets in object literals. See Prettier.
Default | CLI Override | API Override |
---|---|---|
true |
--no-bracket-spacing |
bracketSpacing: <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> |
Other projects
A lot of projects tried to solve this problem, unfortunately, none of them fulfills my use cases.
Using raw node:
Using command line:
Or using a Webpack loader:
Or using a browserify loader:
Or using gulp / grunt plugin:
Or at runtime:
Or using grunt:
License
MIT