Dynamic CSS via prop using CSSModules with React c

2019-07-13 00:36发布

问题:

I'm learning how to use css modules with react, below is a working example of a checkbox here's what it looks like (pure HTML + CSS fiddle) without react.

import React from 'react'
import CSSModules from 'react-css-modules'
import styles from './checkbox.css'

export function Checkbox (props) {
  return <div styleName="checkbox--container">
    <input styleName="checkbox" type="checkbox" {...props}/>
    <span styleName="checkbox--styled"></span>
  </div>
}

export default CSSModules(Checkbox, styles)

This is great and all, but let's say my client comes back and wants me to change the checkbox color. Fine, seems easy enough? That fiddle above shows that there is a couple of hex-codes (#479ccf) for border and within the SVG background image. Ideally I'd be able to pass along a react prop that allows you to do something like this <Checkbox color="#666333"/> and blam! However I can't find any documentation / way to get information from the component to the CSS file.

What does this mean?

I know what the react community is going to say, that particular set of CSS isn't ideal. It can be written in javascript within the component and from there you can set the inline styles of the pieces of the checkbox to the prop color. I'm pretty sure this is possible. Is this necessary? I'd have to refactor the ::after code, question about that.

I started on making the SVG functions.

function SVGDash (color) {
  return `data:image/svg+xml;charset=US-ASCII,<svg%20xmlns%3D"http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg"%20viewBox%3D"0%200%2012%2012"%20enable-background%3D"new%200%200%2012%2012"><style%20type%3D"text%2Fcss">circle%2Cellipse%2Cline%2Cpath%2Cpolygon%2Cpolyline%2Crect%2Ctext%7Bfill%3A%23${color}%20%21important%3B%20%7D<%2Fstyle><path%20d%3D"M6%200"%2F><path%20d%3D"M.8%207C.3%207%200%206.7%200%206.2v-.4c0-.5.3-.8.8-.8h10.5c.4%200%20.7.3.7.8v.5c0%20.4-.3.7-.8.7H.8z"%2F><%2Fsvg>`
}

function SVGCheck (color) {
  return `data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20enable-background%3D%22new%200%200%2024%2024%22%3E%3Cstyle%20type%3D%22text%2Fcss%22%3Ecircle%2Cellipse%2Cline%2Cpath%2Cpolygon%2Cpolyline%2Crect%2Ctext%7Bfill%3A%23${color}%20%21important%3B%20%7D%3C%2Fstyle%3E%3Cpath%20d%3D%22M23.6%205L22%203.4c-.5-.4-1.2-.4-1.7%200L8.5%2015l-4.8-4.7c-.5-.4-1.2-.4-1.7%200L.3%2011.9c-.5.4-.5%201.2%200%201.6l7.3%207.1c.5.4%201.2.4%201.7%200l14.3-14c.5-.4.5-1.1%200-1.6z%22%2F%3E%3C%2Fsvg%3E`
}

回答1:

You could create a different class composing the class you want to change the color:

.checkbox--styled-red {
  composes: checkbox--styled;
  background-image: url("data:image .... FF0000 ....");
}

And set it in the component when you get the matching props.color:

import React from 'react'
import CSSModules from 'react-css-modules'
import styles from './checkbox.css'

function getStyleNameForColor(color) {
  colorToStyleName = {
    red: 'checkbox--styled-red'
  };
  return colorToStyleName[color] || 'checkbox--styled';
}

export function Checkbox (props) {
  return <div styleName="checkbox--container">
    <input styleName="checkbox" type="checkbox" {...props}/>
    <span styleName={getStyleNameForColor(props.color)}></span>
  </div>
}

export default CSSModules(Checkbox, styles)

Better yet, use classnames instead of getStyleNameFor(color).