简体   繁体   中英

How to apply style to an array of SVG elements

I have an array of .svg icons, where each icon has some properties which I need to override:

<svg width="24" height="24" viewBox="0 0 24 24"> ... </svg>
import styled from 'styled-components';

import Github from 'assets/github.svg';
import Facebook from 'assets/facebook.svg';
import Twitter from 'assets/twitter.svg';
...

const icons = [
  <Github />,
  <Facebook />,
  <Twitter />,
  ...
];

I would like to apply the same styling for each icon without duplicating code and using CSS-in-JS .

My solution so far has some issues:

// Works but,
// I want to use CSS-in-JS like styled-components
// for easier maintenance
const iconStyle = {
  width: 50,
  height: 50
};

const SocialBar = () => (
  <IconBar as={FlexBox}>
    {icons.map((icon, key) => (
      <div key={key}>{React.cloneElement(icon, iconStyle)}</div>
    ))}
  </IconBar>
);
// Works but,
// there are too many icons
const SocialBar = () => (
  <IconBar as={FlexBox}>
    <Github style={iconStyle} />
    <Facebook style={iconStyle} />
    ...
  </IconBar>
);

And styling svg component like this won't work:

// Won't override the width="24" height="24" properties
const StyledIcon = styled(Github)`
  width: 50;
  height: 50;
`;

You can wrap the SVG with an element (like an i ) and style any svg children inside of it with some CSS defined within a styled-component (you can also target g and path as well). Unfortunately, SVGs are pretty tricky to work with, so you may need to manually copy/paste the SVG xml into a JS file (if you're using the CRA , you can import a ReactComponent from an SVG ).

Working example (copy/pasted SVG into JS file -- 1st example is the default, 2nd example passes in props, 3rd example passes in multiple props):

编辑样式化 SVG 组件


Icon/Icon.js (this component accepts a styled component generated className and any children placed inside of it)

import React from "react";
import PropTypes from "prop-types";

const Icon = ({ className, children }) => (
  <i className={className}>{children}</i>
);

Icon.propTypes = {
  className: PropTypes.string.isRequired,
  children: PropTypes.node.isRequired
};

export default Icon;

Icon/index.js (this will style the Icon component above; and, subsequently it will style the children )

import styled from "styled-components";
import Icon from "./Icon";

const StyledIcon = styled(Icon)`
  margin: 0 20px;
  svg {
    fill: ${({ fill }) => fill || "#03a9f3"};
    height: ${({ dimension }) => dimension || "50px"};
    width: ${({ dimension }) => dimension || "50px"};
  }
`;

export default StyledIcon;

This is one way of doing it.

//Github.js
import React from "react";
export default function Github({height, width}) {
    return (
        <svg width={width} height={height} viewBox="0 0 24 24"> ...  </svg>
    );
}

Then where you want to use it.

<Github height={24} width={24} />

I'm not entirely sure what your request is, relative to the code samples you already have. Are you trying to avoid using React.cloneElement ? Make the array of icons as functions, instead of a jsx element. map over it to the jsx version and apply the styles to each

const icons = [
  Github,
  Facebook,
  Twitter,
]

buildIcons() {
  const style = {
    //..
  }
  return icons.map((icon, idx) => (
    <icon style={style} key={idx}/>
  ))

}

Using index as the key works, but if you can find a different property that is unique to each icon, it'd be better.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM