使用作用域 CSS 创建 SVG 组件

7

我正在创建React组件,用于渲染各种SVG:

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>
);

能够向该组件提供各种属性以控制尺寸、颜色等非常方便...

然而,我没有一个好的解决方案来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呢? - Sakhi Mansoor
@MisterEpic,我有点困惑你在寻找什么。每个SVG都是独一无二的,为什么你想要在它们之间共享样式呢? - Martin Dawson
1
那么css-modules(https://github.com/css-modules/css-modules)怎么样?它是否符合您的要求? - An Nguyen
1
对于作用域样式,请考虑使用 Shadow DOM。对于 Edge 浏览器,请使用 polyfills。 - Benny Powers
@MisterEpic,OP去哪了? - Ted
3个回答

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 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'));

还有一个外部样式文件:

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",
}

这里有实时示例


1
如果你只是想简化代码,可以创建一个样式对象并重复使用它:
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>
  );
}

这也会带来一些性能上的提升,因为在每个渲染周期中创建的对象会更少。

是的,这样更好,但这只是一个小例子。我的真实世界SVG有许多内联样式的变化。 - Mister Epic

0
其实,如果我处在你的位置,我肯定会使用字体而不是SVG,但对于你的具体问题,我更喜欢在箭头函数内部使用常量变量,就像下面这样:
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;

即使我将线条尺寸变量设置为props,但我不知道你的情况是什么。

希望这个答案能帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接