CSS 模块、反应和覆盖 CSS 类
CSS Modules, React and Overriding CSS Classes
我正在使用 React 组件库 (React Toolbox),它使用 CSS 模块和 Webpack 在其 Tab 组件中输出此 class:label___1nGy active___1Jur tab___Le7N
tab
是我传下来的 className 道具。 label
和 active
classes 来自图书馆。我想在 active
上应用一组不同的样式,例如 .tab.active
,其中 tab
指的是我创建的样式,active
匹配库中生成的选择器创建但无法弄清楚如何使用 css-modules 执行此操作。我需要覆盖这个动态选择器:.label___1nGy.active___1Jur
.
[]]2
[]3
CSS 模块不允许您安全地覆盖活动类名(主要是设计使然)。实际上,它应该通过 API 公开,例如'activeClassName'.
如果维护者不同意或者您需要快速完成,那么您可以很容易地添加自己的活动类名,因为您的实施组件正在管理索引状态:
import {Tab, Tabs} from 'react-toolbox';
import styles from './MyTabs.css';
class MyTabs extends React.Component {
state = {
index: 1
};
handleTabChange(index) {
this.setState({ index });
}
render() {
const { index } = this.state;
return (
<Tabs index={index} onChange={this.handleTabChange}>
<Tab label="Tab0" className={index === 0 ? styles.active : null}>
Tab 0 content
</Tab>
<Tab label="Tab1" className={index === 1 ? styles.active : null}>
Tab 1 content
</Tab>
</Tabs>
);
}
}
免责声明:代码未经测试。
我也遇到过类似的情况,我是这样解决的:
import classNames from 'classnames';
...
const activeClassName = {};
activeClassName[`${styles.active}`] = this.props.isActive;
const elementClassNames = classNames(styles.element, activeClassName);
return <div className={elementClassNames} />
我正在使用 classnames
包根据 isActive
道具动态添加活动 class。您可以提供任何布尔值,而不是 isActive
道具。
更简洁的方法可能是:
const elementClassNames = classNames(styles.element, {[styles.active]: this.props.isActive});
旧 post 但仍然相关,因此添加一个答案以帮助那些有类似问题的人
虽然在 CSS 模块中本身不可能,但 react-toolbox 库的作者实际上很好地解决了这个特殊问题
阅读他们的 github 文档,这些文档在 https://github.com/react-toolbox/react-toolbox#customizing-components
上更深入地介绍了该主题
他们网站上的组件演示页面上也给出了特定组件的可主题化 类 列表
在您的情况下,除了为选项卡传递 className 之外,您还可以使用 类 创建一个主题,该主题覆盖默认主题的所需部分并将其作为 theme
道具传递。例如一些类似...
的行
MyComponentWithTabs.css
.tab {
color: white;
}
MyTabTheme.css
.active {
color: hotpink;
}
MyComponentWithTabs.js
import styles from './MyComponentWithTabs.css'
import tabTheme from './MyTabTheme.css'
// blah blah...
return <Tab key={index} className={styles.tab} theme={tabTheme} />
在表面之下,这使用了一个装饰器,他们已经抽象到单独的库中 react-css-themr,我建议您也阅读一下,因为它更深入地解释了默认值是如何与您的覆盖组合的,包括不同的合并他们使用的策略
分组样式加载器
您可以使用 group-style-lader 来覆盖组件的样式。这个加载器为您提供了一种简单直观的方法来覆盖组件的样式。
配置加载程序
安装加载程序
npm install --save-dev group-style-loader
在你的 webpack 设置中配置加载器
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'group-style-loader',
'style-loader',
{
loader: "css-loader",
options: {
modules: true
}
}
]
}
]
}
};
You only need to put it, before the style-loader
or the mini-css-extract-plugin
loader.
覆盖组件的样式
The next example show as you can to override the style of the Card component from the App component.
您可以按照习惯定义组件的样式。
card.css
.container {
width: 300px;
height: 400px;
border-radius: 8px;
}
.title {
font-weight: bold;
font-size: 24px;
}
.summary {
margin-top: 24px;
font-size: 20px;
}
独特的区别在于,在Card组件中,您将使用mergeStyle
函数将自定义样式与组件的默认样式合并。
card.jsx
import React from 'react';
import { mergeStyle } from './card.css';
export function Card({ customStyle }) {
const style = mergeStyle(customStyle);
return (
<div className={style.container}>
<div className={style.title}>Title</div>
<div className={style.summary}>
Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor.
</div>
</div>
)
}
然后,在App组件中,要覆盖Card组件的样式,您需要定义Card的自定义样式使用分隔符 _
的组件。所有使用此分隔符的 类 将在样式对象的 card 属性 中分组。
app.jsx
.title {
font-size: 32px;
font-weight: bold;
margin: 44px;
}
.list {
display: flex;
}
.card_title {
color: blue;
}
.card_summary {
color: green;
}
最后只需要将Card组件的自定义样式通过它的customStyle
属性即可。
app.jsx
import React from 'react';
import { Card } from './card';
import { style } from './app.css';
export function App() {
return (
<div>
<h1 className={style.title}>Group style</h1>
<div className={style.list}>
<Card/>
<Card customStyle={style.card}/>
</div>
</div>
);
}
在前面的示例中,您有两个 Cards 组件,第一个使用其默认样式,第二个使用我们定义的自定义样式。
您可以在 repository.
中查看如何使用 group-style-loader
的完整说明
fileName.css
中的技巧
在声明类名
后添加className-active
.className{
background: white;
}
.className-active{
background: black;
}
<div className={'className className-active'} />
<div className={'className-active className'} />
divs 永远是黑色
使用 :global(.classname) 你可以覆盖外部类名。
甚至可以覆盖第 3 方库 css。
:global(.active) {
color: hotpink;
}
我正在使用 React 组件库 (React Toolbox),它使用 CSS 模块和 Webpack 在其 Tab 组件中输出此 class:label___1nGy active___1Jur tab___Le7N
tab
是我传下来的 className 道具。 label
和 active
classes 来自图书馆。我想在 active
上应用一组不同的样式,例如 .tab.active
,其中 tab
指的是我创建的样式,active
匹配库中生成的选择器创建但无法弄清楚如何使用 css-modules 执行此操作。我需要覆盖这个动态选择器:.label___1nGy.active___1Jur
.
[
CSS 模块不允许您安全地覆盖活动类名(主要是设计使然)。实际上,它应该通过 API 公开,例如'activeClassName'.
如果维护者不同意或者您需要快速完成,那么您可以很容易地添加自己的活动类名,因为您的实施组件正在管理索引状态:
import {Tab, Tabs} from 'react-toolbox';
import styles from './MyTabs.css';
class MyTabs extends React.Component {
state = {
index: 1
};
handleTabChange(index) {
this.setState({ index });
}
render() {
const { index } = this.state;
return (
<Tabs index={index} onChange={this.handleTabChange}>
<Tab label="Tab0" className={index === 0 ? styles.active : null}>
Tab 0 content
</Tab>
<Tab label="Tab1" className={index === 1 ? styles.active : null}>
Tab 1 content
</Tab>
</Tabs>
);
}
}
免责声明:代码未经测试。
我也遇到过类似的情况,我是这样解决的:
import classNames from 'classnames';
...
const activeClassName = {};
activeClassName[`${styles.active}`] = this.props.isActive;
const elementClassNames = classNames(styles.element, activeClassName);
return <div className={elementClassNames} />
我正在使用 classnames
包根据 isActive
道具动态添加活动 class。您可以提供任何布尔值,而不是 isActive
道具。
更简洁的方法可能是:
const elementClassNames = classNames(styles.element, {[styles.active]: this.props.isActive});
旧 post 但仍然相关,因此添加一个答案以帮助那些有类似问题的人
虽然在 CSS 模块中本身不可能,但 react-toolbox 库的作者实际上很好地解决了这个特殊问题
阅读他们的 github 文档,这些文档在 https://github.com/react-toolbox/react-toolbox#customizing-components
上更深入地介绍了该主题他们网站上的组件演示页面上也给出了特定组件的可主题化 类 列表
在您的情况下,除了为选项卡传递 className 之外,您还可以使用 类 创建一个主题,该主题覆盖默认主题的所需部分并将其作为 theme
道具传递。例如一些类似...
MyComponentWithTabs.css
.tab {
color: white;
}
MyTabTheme.css
.active {
color: hotpink;
}
MyComponentWithTabs.js
import styles from './MyComponentWithTabs.css'
import tabTheme from './MyTabTheme.css'
// blah blah...
return <Tab key={index} className={styles.tab} theme={tabTheme} />
在表面之下,这使用了一个装饰器,他们已经抽象到单独的库中 react-css-themr,我建议您也阅读一下,因为它更深入地解释了默认值是如何与您的覆盖组合的,包括不同的合并他们使用的策略
分组样式加载器
您可以使用 group-style-lader 来覆盖组件的样式。这个加载器为您提供了一种简单直观的方法来覆盖组件的样式。
配置加载程序
安装加载程序
npm install --save-dev group-style-loader
在你的 webpack 设置中配置加载器
module.exports = { module: { rules: [ { test: /\.css$/i, use: [ 'group-style-loader', 'style-loader', { loader: "css-loader", options: { modules: true } } ] } ] } };
You only need to put it, before the
style-loader
or themini-css-extract-plugin
loader.
覆盖组件的样式
The next example show as you can to override the style of the Card component from the App component.
您可以按照习惯定义组件的样式。
card.css
.container {
width: 300px;
height: 400px;
border-radius: 8px;
}
.title {
font-weight: bold;
font-size: 24px;
}
.summary {
margin-top: 24px;
font-size: 20px;
}
独特的区别在于,在Card组件中,您将使用mergeStyle
函数将自定义样式与组件的默认样式合并。
card.jsx
import React from 'react';
import { mergeStyle } from './card.css';
export function Card({ customStyle }) {
const style = mergeStyle(customStyle);
return (
<div className={style.container}>
<div className={style.title}>Title</div>
<div className={style.summary}>
Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor.
</div>
</div>
)
}
然后,在App组件中,要覆盖Card组件的样式,您需要定义Card的自定义样式使用分隔符 _
的组件。所有使用此分隔符的 类 将在样式对象的 card 属性 中分组。
app.jsx
.title {
font-size: 32px;
font-weight: bold;
margin: 44px;
}
.list {
display: flex;
}
.card_title {
color: blue;
}
.card_summary {
color: green;
}
最后只需要将Card组件的自定义样式通过它的customStyle
属性即可。
app.jsx
import React from 'react';
import { Card } from './card';
import { style } from './app.css';
export function App() {
return (
<div>
<h1 className={style.title}>Group style</h1>
<div className={style.list}>
<Card/>
<Card customStyle={style.card}/>
</div>
</div>
);
}
在前面的示例中,您有两个 Cards 组件,第一个使用其默认样式,第二个使用我们定义的自定义样式。
您可以在 repository.
中查看如何使用group-style-loader
的完整说明
fileName.css
中的技巧在声明类名
后添加className-active.className{
background: white;
}
.className-active{
background: black;
}
<div className={'className className-active'} />
<div className={'className-active className'} />
divs 永远是黑色
使用 :global(.classname) 你可以覆盖外部类名。
甚至可以覆盖第 3 方库 css。
:global(.active) {
color: hotpink;
}