如何使 React CSS 导入组件范围?

我有几个组件,它们具有以下 CSS/组件结构

About/style.css

.AboutContainer {
# Some style
}


p > code {
# Some style
}

我在组件中导入 CSS,如下所示

About/index.js

import './style.css';


export default class About extends Component {
render() {
# Return some component
}
}

但是,CSS 在 <header>部分中导入,并保持全局范围。

我期望 CSS 是:

  1. 组件范围,样式只应用于在此组件内呈现的 只有
  2. 如果卸载该组件,则此组件的样式将消失。

但是,当从浏览器检查时,样式在 <header>部分指定,并应用到所有组件

<header>
// Stuff
<style type="text/css">style for component About</style>
<style type="text/css">style for component B</style>
<style type="text/css">style for component C</style>
// Stuff
</header>

如何将 CSS 导入到组件范围? 看起来我在 React ES6中对 CSS 导入的理解是不正确的。

我在跟踪 本教程


剪辑

布雷特的回答是正确的。然而,我的问题出在别的地方。我使用 创建-反应-应用程序创建了我的应用程序,它基本上简化了做 React 所需的设置。它包括 WebPack,Babel 和其他东西开始。它使用的默认 WebPack 配置没有为 css-loader设置 模组选项,因此它默认为 false,结果是没有启用本地范围。

仅仅为了获得更多的信息,create-response-app 似乎没有直接的方法来定制 WebPack 配置,但是在 web 上似乎有许多解决方法。

98840 次浏览

It sounds like CSS Modules, or many of the other CSS-in-JS packages, does what you want. Others include Emotion (my current favorite), Styled Components, or many of the packages here.

A CSS Module is a CSS file in which all class names and animation names are scoped locally by default. All URLs (url(...)) and @imports are in module request format (./xxx and ../xxx means relative, xxx and xxx/yyy means in modules folder, i. e. in node_modules).

Here's a quick example:

Let's say we have a React component like:

import React from 'react';
import styles from './styles/button.css';


class Button extends React.Component {
render() {
return (
<button className={styles.button}>
Click Me
</button>
);
}
}
export default Button;

and some CSS in ./styles/button.css of:

.button {
border-radius: 3px;
background-color: green;
color: white;
}

After CSS Modules performs it's magic the generated CSS will be something like:

.button_3GjDE {
border-radius: 3px;
background-color: green;
color: white;
}

where the _3DjDE is a randomly generated hash - giving the CSS class a unique name.

An Alternative

A simpler alternative would be to avoid using generic selectors (like p, code, etc) and adopt a class-based naming convention for components and elements. Even a convention like BEM would help in preventing the conflicts you're encountering.

Applying this to your example, you might go with:

.aboutContainer {
# Some style
}


.aboutContainer__code {
# Some style
}

Essentially all elements you need to style would receive a unique classname.

You can use SASS (.scss) to imitate scoped CSS.

Say you need to use bootstrap in only one component (to avoid conflicts). Wrap the component in <div className='use-bootstrap'> and then created a .scss file like so:

.use-bootstrap {
// Paste bootstrap.min.css here
}

Maybe react-scoped-css will help. Btw, I'm the author of this lib, if you find anything broken or simply want to improve it, you can always raise an issue or send a pr.

Because you mentioned you used create-react-app, the solution here is quite easy change just style.css to style.module.css, it will look like this:

import styles from "./style.module.css"
<button className={styles.button}>blabla</button>

More info on this article: https://blog.bitsrc.io/how-to-use-sass-and-css-modules-with-create-react-app-83fa8b805e5e

Use this file naming convention [name].module.css and see documentation: https://create-react-app.dev/docs/adding-a-sass-stylesheet

JSX File

import React from 'react';
import styles from './index.module.scss';


const MyPage = () => {
return (
<div className={styles}>
<h1>My Page</h1>
</div>
);
};


export default MyPage;

Styles File

    h1 {
color: #f3f3f3;
font-family: "Cambria";
font-weight: normal;
font-size: 2rem;
}

For me, the simple solution (without using: Css-modules or css-in-js) is to add a suffix to your class selectors like this:

className="btn__suffix"

if your component is named: FileUpload.tsx so your __suffix would be __fu, i took the first character of each word (here: File and Upload).

the end result would be:

import './style.css';


export default class About extends Component {
render() {
Return (
<div className="container__fu">
...
</div>
)
}
}

And in the Css part, your file would be:

.container__fu {
...
}