I am creating React components that will render out various SVGs:
const Close = ({
fill, width, height, float,
}) => (
<svg width={ `${width}px` } height={ `${height}px` } viewBox="0 0 14.48 14.48" style={ { float: `${float}`, cursor: 'pointer' } }>
<title>x</title>
<g id="Layer_2" data-name="Layer 2">
<g id="Background">
<line style={ { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 } } x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
<line style={ { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 } } x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
</g>
</g>
</svg>
);
It's very convenient to be able to supply various attributed to this component to control dimensions, colour, etc...
What I don't have a good solution for, however, is handling the styles in a DRY manner. Note the line elements have the same value for style. I presently have them written inline because if I added an embedded stylesheet, then I would get class name collisions with other SVGs I render elsewhere on the page (our SVG software uses the same classes over and over).
<style scoped> has been removed from the spec: https://github.com/whatwg/html/issues/552
Shadow DOM is not yet supported by Edge: https://caniuse.com/#feat=shadowdomv1
Is there any other alternative for scoping styles?
To combine the best of both worlds, you could create an external styles file, as you would for CSS, but with exported style objects. You could then import it into any file that needs it.
As example, main file:
import React, { Component } from 'react';
import { render } from 'react-dom';
import * as Styles from './svgstyles';
class App extends Component {
render() {
return (
<div>
<svg width="100" height="200" viewBox="0 0 100 200">
<rect x="0" y="0" width="10" height="10" style={Styles.style1} />
<rect x="15" y="0" width="10" height="10" style={Styles.style2} />
<rect x="30" y="0" width="10" height="10" style={Styles.style3} />
<rect x="45" y="0" width="10" height="10" style={Styles.style4} />
<rect x="0" y="15" width="10" height="10" style={Styles.style4} />
<rect x="15" y="15" width="10" height="10" style={Styles.style3} />
<rect x="30" y="15" width="10" height="10" style={Styles.style2} />
<rect x="45" y="15" width="10" height="10" style={Styles.style1} />
</svg>
</div>
);
}
}
render(<App />, document.getElementById('root'));
And an external styles file:
export const style1 = {
stroke: 'red',
strokeWidth: "1",
fill: "blue",
}
export const style2 = {
stroke: 'red',
strokeWidth: "1",
fill: "green",
}
export const style3 = {
stroke: 'red',
strokeWidth: "1",
fill: "yellow",
}
export const style4 = {
...style3,
fill: "pink",
}
Live example here
If you just want to DRY up the code, you could create one style-object and reuse it:
const Close = ({
fill, width, height, float,
}) => {
const style = { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 }
return (
<svg width={ `${width}px` } height={ `${height}px` } viewBox="0 0 14.48 14.48" style={ { float: `${float}`, cursor: 'pointer' } }>
<title>x</title>
<g id="Layer_2" data-name="Layer 2">
<g id="Background">
<line style={ style } x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
<line style={ style } x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
</g>
</g>
</svg>
);
}
This would also result in a small performance improvement since fewer objects would be created in each render cycle.
Actually, if I was in your place, Surely I use fonts instead of SVGs, but for your exact question, I prefer to use constant variables inside of my arrow function, just like below:
import React from 'react';
const Close = ({ fill, width, height, float }) => {
const constStyle = { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 };
return (
<svg
width={`${width}px`}
height={`${height}px`}
viewBox="0 0 14.48 14.48"
style={{ float: `${float}`, cursor: 'pointer' }}
>
<title>x</title>
<g id="Layer_2" data-name="Layer 2">
<g id="Background">
<line style={constStyle} x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
<line style={constStyle} x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
</g>
</g>
</svg>
);
};
export default Close;
Even, I make the line dimension variables as props, but I don't know what is your case exactly.
Hope this answer helps you.
I'm using the following SVG of a Google Play download button. There are 4 <linearGradient> inside <defs>.
<linearGradient> requires an ID for CSS to reference as a fill. I'd rather not use IDs since I'm going to have two of these icons on a single page, causing the page to have duplicate IDs. Any ideas of an alternative way to achieve this?
SVG Code:
<svg viewBox='0 0 135 40'>
<path d='M130,40H5c-2.8,0-5-2.2-5-5V5c0-2.7,2.2-5,5-5h125c2.8,0,5,2.2,5,5v30C135,37.7,132.8,40,130,40z'/>
<path className='st0' d='M130,0.8c2.3,0,4.2,1.9,4.2,4.2v30c0,2.3-1.9,4.2-4.2,4.2H5c-2.3,0-4.2-1.9-4.2-4.2V5c0-2.3,1.9-4.2,4.2-4.2 H130 M130,0H5C2.3,0,0,2.3,0,5v30c0,2.8,2.2,5,5,5h125c2.8,0,5-2.2,5-5V5C135,2.3,132.8,0,130,0L130,0z'/>
<path className='st1' d='M47.4,10.2c0,0.8-0.2,1.5-0.7,2c-0.6,0.6-1.3,0.9-2.2,0.9c-0.9,0-1.6-0.3-2.2-0.9c-0.6-0.6-0.9-1.3-0.9-2.2 c0-0.9,0.3-1.6,0.9-2.2c0.6-0.6,1.3-0.9,2.2-0.9c0.4,0,0.8,0.1,1.2,0.3c0.4,0.2,0.7,0.4,0.9,0.7l-0.5,0.5 c-0.4-0.5-0.9-0.7-1.6-0.7c-0.6,0-1.2,0.2-1.6,0.7c-0.5,0.4-0.7,1-0.7,1.7s0.2,1.3,0.7,1.7c0.5,0.4,1,0.7,1.6,0.7 c0.7,0,1.2-0.2,1.7-0.7c0.3-0.3,0.5-0.7,0.5-1.2h-2.2V9.8h2.9C47.4,9.9,47.4,10.1,47.4,10.2z'/>
<path className='st1' d='M52,7.7h-2.7v1.9h2.5v0.7h-2.5v1.9H52V13h-3.5V7H52V7.7z'/>
<path className='st1' d='M55.3,13h-0.8V7.7h-1.7V7H57v0.7h-1.7V13z' />
<path className='st1' d='M59.9,13V7h0.8v6H59.9z' />
<path className='st1' d='M64.1,13h-0.8V7.7h-1.7V7h4.1v0.7h-1.7V13z' />
<path className='st1' d='M73.6,12.2c-0.6,0.6-1.3,0.9-2.2,0.9c-0.9,0-1.6-0.3-2.2-0.9c-0.6-0.6-0.9-1.3-0.9-2.2s0.3-1.6,0.9-2.2 c0.6-0.6,1.3-0.9,2.2-0.9c0.9,0,1.6,0.3,2.2,0.9c0.6,0.6,0.9,1.3,0.9,2.2C74.5,10.9,74.2,11.6,73.6,12.2z M69.8,11.7 c0.4,0.4,1,0.7,1.6,0.7s1.2-0.2,1.6-0.7c0.4-0.4,0.7-1,0.7-1.7S73.5,8.7,73,8.3c-0.4-0.4-1-0.7-1.6-0.7s-1.2,0.2-1.6,0.7 c-0.4,0.4-0.7,1-0.7,1.7S69.3,11.3,69.8,11.7z'/>
<path className='st1' d='M75.6,13V7h0.9l2.9,4.7h0l0-1.2V7h0.8v6h-0.8l-3.1-4.9h0l0,1.2V13H75.6z'/>
<path className='st2' d='M68.1,21.8c-2.4,0-4.3,1.8-4.3,4.3c0,2.4,1.9,4.3,4.3,4.3c2.4,0,4.3-1.8,4.3-4.3 C72.4,23.5,70.5,21.8,68.1,21.8z M68.1,28.6c-1.3,0-2.4-1.1-2.4-2.6c0-1.5,1.1-2.6,2.4-2.6c1.3,0,2.4,1,2.4,2.6 C70.5,27.5,69.4,28.6,68.1,28.6z M58.8,21.8c-2.4,0-4.3,1.8-4.3,4.3c0,2.4,1.9,4.3,4.3,4.3c2.4,0,4.3-1.8,4.3-4.3 C63.1,23.5,61.2,21.8,58.8,21.8z M58.8,28.6c-1.3,0-2.4-1.1-2.4-2.6c0-1.5,1.1-2.6,2.4-2.6c1.3,0,2.4,1,2.4,2.6 C61.2,27.5,60.1,28.6,58.8,28.6z M47.7,23.1v1.8h4.3c-0.1,1-0.5,1.8-1,2.3c-0.6,0.6-1.6,1.3-3.3,1.3c-2.7,0-4.7-2.1-4.7-4.8 s2.1-4.8,4.7-4.8c1.4,0,2.5,0.6,3.3,1.3l1.3-1.3c-1.1-1-2.5-1.8-4.5-1.8c-3.6,0-6.7,3-6.7,6.6c0,3.6,3.1,6.6,6.7,6.6 c2,0,3.4-0.6,4.6-1.9c1.2-1.2,1.6-2.9,1.6-4.2c0-0.4,0-0.8-0.1-1.1H47.7z M93.1,24.5c-0.4-1-1.4-2.7-3.6-2.7c-2.2,0-4,1.7-4,4.3 c0,2.4,1.8,4.3,4.2,4.3c1.9,0,3.1-1.2,3.5-1.9l-1.4-1c-0.5,0.7-1.1,1.2-2.1,1.2c-1,0-1.6-0.4-2.1-1.3l5.7-2.4L93.1,24.5z M87.3,25.9c0-1.6,1.3-2.5,2.2-2.5c0.7,0,1.4,0.4,1.6,0.9L87.3,25.9z M82.6,30h1.9V17.5h-1.9V30z M79.6,22.7L79.6,22.7 c-0.5-0.5-1.3-1-2.3-1c-2.1,0-4.1,1.9-4.1,4.3c0,2.4,1.9,4.2,4.1,4.2c1,0,1.8-0.5,2.2-1h0.1v0.6c0,1.6-0.9,2.5-2.3,2.5 c-1.1,0-1.9-0.8-2.1-1.5l-1.6,0.7c0.5,1.1,1.7,2.5,3.8,2.5c2.2,0,4-1.3,4-4.4V22h-1.8V22.7z M77.4,28.6c-1.3,0-2.4-1.1-2.4-2.6 c0-1.5,1.1-2.6,2.4-2.6c1.3,0,2.3,1.1,2.3,2.6C79.7,27.5,78.7,28.6,77.4,28.6z M101.8,17.5h-4.5V30h1.9v-4.7h2.6 c2.1,0,4.1-1.5,4.1-3.9S103.9,17.5,101.8,17.5z M101.9,23.5h-2.7v-4.3h2.7c1.4,0,2.2,1.2,2.2,2.1C104,22.4,103.2,23.5,101.9,23.5z M113.4,21.7c-1.4,0-2.8,0.6-3.3,1.9l1.7,0.7c0.4-0.7,1-0.9,1.7-0.9c1,0,1.9,0.6,2,1.6v0.1c-0.3-0.2-1.1-0.5-1.9-0.5 c-1.8,0-3.6,1-3.6,2.8c0,1.7,1.5,2.8,3.1,2.8c1.3,0,1.9-0.6,2.4-1.2h0.1v1h1.8v-4.8C117.2,23,115.5,21.7,113.4,21.7z M113.2,28.6 c-0.6,0-1.5-0.3-1.5-1.1c0-1,1.1-1.3,2-1.3c0.8,0,1.2,0.2,1.7,0.4C115.2,27.8,114.2,28.6,113.2,28.6z M123.7,22l-2.1,5.4h-0.1 l-2.2-5.4h-2l3.3,7.6l-1.9,4.2h1.9l5.1-11.8H123.7z M106.9,30h1.9V17.5h-1.9V30z'/>
<path className='st3' d='M10.4,7.5C10.1,7.8,10,8.3,10,8.9v22.1c0,0.6,0.2,1.1,0.5,1.4l0.1,0.1l12.4-12.4V20v-0.1L10.4,7.5L10.4,7.5z' />
<path className='st4' d='M27,24.3l-4.1-4.1V20v-0.1l4.1-4.1l0.1,0.1l4.9,2.8c1.4,0.8,1.4,2.1,0,2.9L27,24.3L27,24.3z' />
<path className='st5' d='M27.1,24.2L22.9,20L10.4,32.5c0.5,0.5,1.2,0.5,2.1,0.1L27.1,24.2' />
<path className='st6' d='M27.1,15.8L12.5,7.5c-0.9-0.5-1.6-0.4-2.1,0.1L22.9,20L27.1,15.8z' />
<path className='st7' d='M27,24.1l-14.5,8.2c-0.8,0.5-1.5,0.4-2,0l0,0l-0.1,0.1l0,0l0.1,0.1l0,0c0.5,0.4,1.2,0.5,2,0L27,24.1L27,24.1 z' />
<path className='st8' d='M10.4,32.3C10.1,32,10,31.5,10,30.9v0.1c0,0.6,0.2,1.1,0.5,1.4V32.3L10.4,32.3z' />
<path className='st8' d='M32,21.3l-5,2.8l0.1,0.1l4.9-2.8c0.7-0.4,1-0.9,1-1.4l0,0C33,20.5,32.6,20.9,32,21.3z' />
<path className='st9' d='M12.5,7.6L32,18.7c0.6,0.4,1,0.8,1,1.3l0,0c0-0.5-0.3-1-1-1.4L12.5,7.5C11.1,6.7,10,7.3,10,8.9v0.1 C10,7.5,11.1,6.8,12.5,7.6z' />
<defs>
<linearGradient id='SVGID_1_' gradientUnits='userSpaceOnUse' x1='21.8'
y1='33.29' x2='5.017' y2='16.508' gradientTransform='matrix(1 0 0 -1 0 42)'>
<stop offset='0' stopColor='#00a0ff' />
<stop offset='0.007' stopColor='#00a1ff' />
<stop offset='0.26' stopColor='#00beff' />
<stop offset='0.512' stopColor='#00d2ff' />
<stop offset='0.76' stopColor='#00dfff' />
<stop offset='1' stopColor='#00e3ff' />
</linearGradient>
<linearGradient id='SVGID_2_' gradientUnits='userSpaceOnUse' x1='33.834'
y1='21.999' x2='9.637' y2='21.999' gradientTransform='matrix(1 0 0 -1 0 42)'>
<stop offset='0' stopColor='#ffe000' />
<stop offset='0.409' stopColor='#ffbd00' />
<stop offset='0.775' stopColor='orange' />
<stop offset='1' stopColor='#ff9c00' />
</linearGradient>
<linearGradient id='SVGID_3_' gradientUnits='userSpaceOnUse' x1='24.827'
y1='19.704' x2='2.069' y2='-3.054' gradientTransform='matrix(1 0 0 -1 0 42)'>
<stop offset='0' stopColor='#ff3a44' />
<stop offset='1' stopColor='#c31162' />
</linearGradient>
<linearGradient id='SVGID_4_' gradientUnits='userSpaceOnUse' x1='7.297'
y1='41.824' x2='17.46' y2='31.661' gradientTransform='matrix(1 0 0 -1 0 42)'>
<stop offset='0' stopColor='#32a071' />
<stop offset='0.069' stopColor='#2da771' />
<stop offset='0.476' stopColor='#15cf74' />
<stop offset='0.801' stopColor='#06e775' />
<stop offset='1' stopColor='#00f076' />
</linearGradient>
</defs>
</svg>
CSS:
.st0{
fill:#A6A6A6;
}
.st1{
fill: #FFFFFF;
stroke: #FFFFFF;
stroke-width: 0.2;
stroke-miterlimit: 10;
}
.st2{
fill: #FFFFFF;
}
.st3{
fill: url(#SVGID_1_);
}
.st4{
fill: url(#SVGID_2_);
}
.st5{
fill: url(#SVGID_3_);
}
.st6{
fill: url(#SVGID_4_);
}
.st7{
opacity: 0.2;
enable-background: new;
}
.st8{
opacity: 0.12;
enable-background: new;
}
.st9{
opacity: 0.25;
fill: #FFFFFF;
enable-background:new;
}