React SVG component as background-image to div
Solution 1
Unfortunately, what you're trying to achieve is not possible. You'll have to keep your SVG as an actual .svg file (and link to that), or do some CSS trickery to place SVG component behind your foreground-component.
In other words:
<!-- step.svg -->
<svg version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 193.3 129.7">
<!-- copy paste your svg here -->
</svg>
And in your component:
import stepSvgUrl from "../../components/UI/SVGs/step.
// ...
<Wrap key={step._id} bg={stepSvgUrl}>
When you import an SVG file like that, create-react-app applies a Webpack loader that includes the generated URL to the SVG you're importing - which is fine to pass into the background-image
css property.
Hope this helps!
Solution 2
For React SVG background images, I find this works best:
// MyComponent.js
import mySvg from './mySvg.svg';
...
function MyComponent() {
return (
<div
className="someClassName"
style={{ backgroundImage: `url(${mySvg})` }}
>
... etc
The path to the SVG file will change when webpack bundles, so by using the template string you can keep things linked up.
In the CSS class you can do whatever styling you like.
Solution 3
Actually, there is a way to achieve what you want, without the SVG beeing a component:
Here is the updated StepBar
component:
import React, { Component } from "react";
import StepSVG from "../../components/UI/SVGs/test.svg";
import encodeSVG from '../../lib/encodeSVG';
class StepBar extends Component {
render() {
const { steps } = this.props;
return (
<div>
{steps
? steps.map(step => {
return (
<Wrap key={step._id} bg={StepSVG}>
<P>
{" "}
<Link to={"/step/" + step._id}>{step.title} </Link>
</P>
</Wrap>
);
})
: null}
</div>
);
}
}
export default StepBar;
const Wrap = styled.div`
padding: 30px 30px 0 0;
display: inline-block;
background-image: ${encodeSVG(bg, '#FF9900')};
`;
Here is encodeSVG
lib file:
var symbols = /[\r\n"%#()<>?\[\\\]^`{|}]/g;
function addNameSpace(data) {
if (data.indexOf('http://www.w3.org/2000/svg') < 0) {
data = data.replace(/<svg/g, "<svg xmlns='http://www.w3.org/2000/svg'");
}
return data;
}
function encodeSVG(data) {
// Use single quotes instead of double to avoid encoding.
if (data.indexOf('"') >= 0) {
data = data.replace(/"/g, "'");
}
data = data.replace(/>\s{1,}</g, '><');
data = data.replace(/\s{2,}/g, ' ');
return data.replace(symbols, encodeURIComponent);
}
var encode = function(svg, fill) {
if (fill) {
svg = svg.replace(/<svg/g, `<svg fill="${fill}"`);
}
var namespaced = addNameSpace(svg);
var dimensionsRemoved = namespaced
.replace(/height="\w*" /g, '')
.replace(/width="\w*" /g, '')
.replace(/height='\w*' /g, '')
.replace(/width='\w*' /g, '');
var encoded = encodeSVG(dimensionsRemoved);
var header = 'data:image/svg+xml,';
var dataUrl = header + encoded;
return `url("${dataUrl}")`;
};
You import the svg, and use a string loader for svgs with your preferred build system (for example WebPack), pass that svg to encodeSVG, et voila! :)
Solution 4
I ended up using user11011301's solution in combination with raw-loader to load the SVG content. Not the cleanest solution I'm sure, but I couldn't get it to work with other webpack loaders.
import searchIcon from '../../images/search.svg';
<input style={{backgroundImage: `url(data:image/svg+xml;base64,${btoa(searchIcon)})`}}/>
Solution 5
url(`data:image/svg+xml;utf8,${svgTxt}`)
;or
url(`data:image/svg+xml;base64,${btoa(svgTxt)}`)
that's it.
Related videos on Youtube
user8467470
Updated on July 09, 2022Comments
-
user8467470 almost 2 years
I am trying to get styled-components to take an SVG that is a react component and set it as a background-image but I get the error:
TypeError: Cannot convert a Symbol value to a string
SVG component code:
import React from "react"; const testSVG = props => { return ( <svg version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 193.3 129.7"> <g> <g> <g> <path fill="#434343" class="st0" d="M162.4,116c-4.6,7.5-15.6,13.6-24.4,13.6H16c-8.8,0-12.3-6.2-7.7-13.7c0,0,4.6-7.7,11.1-18.4 c4.4-7.4,8.9-14.7,13.3-22.1c1.1-1.8,6.1-7.7,6.1-10.1c0-7.3-15-24.9-18.5-30.7C13.5,23.6,8.3,14.9,8.3,14.9 C3.7,7.4,7.2,1.2,16,1.2c0,0,65.9,0,106.8,0c10,0,25.9-4.5,33.5,3.8c8.7,9.3,15.5,25.4,22.5,36.8c2.6,4.2,14.5,18.3,14.5,23.8 c-0.1,7.6-16,26.1-19.6,32C167.1,108.3,162.4,116,162.4,116z" /> </g> </g> </g> </svg> ); }; export default testSVG;
Container component code:
import React, { Component } from "react"; import StepSVG from "../../components/UI/SVGs/Test"; class StepBar extends Component { render() { const { steps } = this.props; return ( <div> {steps ? steps.map(step => { return ( <Wrap key={step._id} bg={StepSVG}> <P> {" "} <Link to={"/step/" + step._id}>{step.title} </Link> </P> </Wrap> ); }) : null} </div> ); } } export default StepBar; const Wrap = styled.div` padding: 30px 30px 0 0; display: inline-block; background-image: url(${props => props.bg}); `;
I am using create-react-app out of the box.
I also tried without using styled components and used inline styles in place to no success.
Is it possible to use an SVG as a background-image in this context with the SVG being a component?
-
user8467470 almost 6 yearsThanks. This was my original approach but I am trying to render the colors dynamically. I guess I would just have to create N number of static SVGs for each colour in this approach?
-
Kris Selbekk almost 6 yearsThat's one way to do it, but you can still use your original approach. In that case you'd have to layer the SVG below your content with CSS (the z-index prop will help with that).
-
user8467470 almost 6 yearsThanks Kris, As my original approach just doesn't seem possible for now I will select this as Solved. I appreciate the help.
-
johannes_lalala about 3 yearsthe question was about creating an svg as react component, not loading a normal svg from a file
-
Navidot almost 3 years
bg
variable is not initialized in your example.