Reputation: 6810
I have a SVG file that I want to use as an icon in my react component.
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 409.6 405.76"><defs><style>.cls-1{fill:none;}.cls-2{clip-path:url(#clip-path);}</style><clipPath id="clip-path" transform="translate(-478 -181.08)"><rect class="cls-1" x="478" y="181" width="409.92" height="406.8"/></clipPath></defs><title>test</title><g class="cls-2"><path class="ofj" d="M682.8,396.06c50.72,0,91.84-48.13,91.84-107.49,0-82.33-41.12-107.49-91.84-107.49S591,206.24,591,288.57c0,59.36,41.12,107.49,91.84,107.49Zm0,0" transform="translate(-478 -181.08)"/><path d="M885.6,554.28,839.27,449.9a23.3,23.3,0,0,0-10.48-11.15l-71.91-37.43a4.66,4.66,0,0,0-4.93.41,113.41,113.41,0,0,1-138.3,0,4.67,4.67,0,0,0-4.94-.41l-71.9,37.43a23.24,23.24,0,0,0-10.47,11.15L480,554.28a23.16,23.16,0,0,0,21.18,32.56H864.42a23.17,23.17,0,0,0,21.18-32.56Zm0,0" transform="translate(-478 -181.08)"/></g></svg>
I want to be able to change the fill color dynamically. I've read that it's best to use SVG 'inline' and I tried to reference it with a <use>
but it does not work (it's not showing...)
<svg className="icon-avator">
<use xlinkHref="./assets/avatar.svg" />
</svg>
How can I achieve this?
Upvotes: 8
Views: 21150
Reputation: 169
There is also a npm package that converts all svg elements to the correct JSX incase anyone else came here and stumbled with a similar problem.
https://www.npmjs.com/package/convert-svg-react
Upvotes: 1
Reputation: 1179
Another option is to not use an external source, so instead of doing
<use href="/path/to/icon.svg" />
create a sprite with symbols (e.g. with https://www.npmjs.com/package/svg-sprite) like that:
<svg ...>
// icon contents here, except `svg` tag became `symbol` tag
<symbol id="icon-id-inside-the-sprite" ...>
// ...
</symbol>
// may be add more icons
</svg>
inline it into your HTML somewhere and hide with display: none
style, then use it like
<use href="#icon-id-inside-the-sprite" />
Now you should be able to target its inner classes from your outside CSS.
Upvotes: 0
Reputation: 3487
For people landing on this page, there is also a webpack loader which generates React components from SVG files. react-svg-loader
If you are using create-react-app, you might want to eject for now. But know this; there are discussions about integrating such a loader in CRA and it's on the 2.0.0 roadmap apparently
Upvotes: 2
Reputation: 191976
React JSX can produce SVG, the same way it does with HTML. Write the SVG as the component's "markup", and use props to control the fill
attribute (you can also change the style):
const Icon = ({ fill }) => (
<svg viewBox="0 0 409.6 405.76" fill={ fill }>
<path d="M682.8,396.06c50.72,0,91.84-48.13,91.84-107.49,0-82.33-41.12-107.49-91.84-107.49S591,206.24,591,288.57c0,59.36,41.12,107.49,91.84,107.49Zm0,0" transform="translate(-478 -181.08)"/>
<path d="M885.6,554.28,839.27,449.9a23.3,23.3,0,0,0-10.48-11.15l-71.91-37.43a4.66,4.66,0,0,0-4.93.41,113.41,113.41,0,0,1-138.3,0,4.67,4.67,0,0,0-4.94-.41l-71.9,37.43a23.24,23.24,0,0,0-10.47,11.15L480,554.28a23.16,23.16,0,0,0,21.18,32.56H864.42a23.17,23.17,0,0,0,21.18-32.56Zm0,0" transform="translate(-478 -181.08)"/>
</svg>
);
ReactDOM.render(
<Icon fill="red" />,
demo
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="demo"></div>
Upvotes: 11