使用作用域 CSS 创建 SVG 组件
Posted
技术标签:
【中文标题】使用作用域 CSS 创建 SVG 组件【英文标题】:Create SVG components with scoped CSS 【发布时间】:2019-02-22 14:04:59 【问题描述】:我正在创建将呈现各种 SVG 的 React 组件:
const Close = (
fill, width, height, float,
) => (
<svg width= `$widthpx` height= `$heightpx` 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>
);
能够提供该组件的各种属性来控制尺寸,颜色等非常方便......
然而,我没有一个好的解决方案是以 DRY 方式处理样式。请注意line
元素与style
具有相同的值。我现在将它们内联编写,因为如果我添加了一个嵌入式样式表,那么我会与我在页面上其他地方渲染的其他 SVG 发生类名冲突(我们的 SVG 软件一遍又一遍地使用相同的类)。
<style scoped>
已从规范中删除:https://github.com/whatwg/html/issues/552
Edge 还不支持Shadow DOM:https://caniuse.com/#feat=shadowdomv1
范围样式还有其他替代方法吗?
【问题讨论】:
嗨@Mister。你为什么不去 css-in-js。 ? @MisterEpic 我对你在找什么有点困惑。每个 SVG 都非常独特,那么为什么要在它们之间共享样式呢? css-modules (github.com/css-modules/css-modules) 怎么样?它符合您的要求吗? 对于范围样式,请考虑使用 shadow DOM。对于边缘,使用 polyfills @MisterEpic OP 去哪儿了? 【参考方案1】:实际上,如果我在你的位置,我当然会使用字体而不是 SVG,但是对于你的确切问题,我更喜欢在箭头函数中使用常量变量,如下所示:
import React from 'react';
const Close = ( fill, width, height, float ) =>
const constStyle = fill: 'none', stroke: `$fill`, strokeMiterlimit: 10 ;
return (
<svg
width=`$widthpx`
height=`$heightpx`
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;
即使,我将线尺寸变量设为props
,但我不知道你的具体情况。
希望这个答案对你有所帮助。
【讨论】:
【参考方案2】:要结合两全其美,您可以创建一个外部样式文件,就像创建 CSS 一样,但要使用导出的样式对象。然后,您可以将其导入到任何需要它的文件中。
例如,主文件:
import React, Component from 'react';
import render from 'react-dom';
import * as Styles from './svgstyles';
class App extends Component
render()
return (
<div>
<svg viewBox="0 0 100 200">
<rect x="0" y="0" style=Styles.style1 />
<rect x="15" y="0" style=Styles.style2 />
<rect x="30" y="0" style=Styles.style3 />
<rect x="45" y="0" style=Styles.style4 />
<rect x="0" y="15" style=Styles.style4 />
<rect x="15" y="15" style=Styles.style3 />
<rect x="30" y="15" style=Styles.style2 />
<rect x="45" y="15" style=Styles.style1 />
</svg>
</div>
);
render(<App />, document.getElementById('root'));
还有一个外部样式文件:
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
【讨论】:
【参考方案3】:如果你只是想干掉代码,你可以创建一个样式对象并重用它:
const Close = (
fill, width, height, float,
) =>
const style = fill: 'none', stroke: `$fill`, strokeMiterlimit: 10
return (
<svg width= `$widthpx` height= `$heightpx` 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>
);
这也将导致性能小幅提升,因为在每个渲染周期中创建的对象更少。
【讨论】:
是的,这样更好,但这是一个小例子。我在现实世界中的 SVG 有多种内联样式。以上是关于使用作用域 CSS 创建 SVG 组件的主要内容,如果未能解决你的问题,请参考以下文章