I have several components which have the following CSS/component structure
About/style.css
.AboutContainer {
# Some style
}
p > code {
# Some style
}
And I import the CSS in the componet as follows
About/index.js
import './style.css';
export default class About extends Component {
render() {
# Return some component
}
}
However, the CSS is imported in the <header>
section and stays global-scope.
I was expecting CSS to be:
- Component-scoped in a way that the style is only applied to things that are only rendered within this component.
- Style for this component would disappear if the component is unmounted.
However, when inspecting from the browser, the styles are specified at the <header>
section and gets applied to all the components
<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>
How do I import CSS to be component-scoped? It seems like I'm understanding CSS import in React ES6 incorrectly.
I was following this tutorial
Edit
Answer by Brett is correct. However, my problem turns out to be somewhere else. I created my app using create-react-app which basically simplifies setups required to do React. It include WebPack, Babel and other things to get started. The default WebPack config that it uses did not set module option for the css-loader
so it defaulted to false
, and as a result the local-scoping was not enabled.
Just for additional info, it seems like create-react-app does not have straightforward way to customize WebPack config, but there seem to be numerous how-to workarounds on the web.
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.
Here's a quick example:
Let's say we have a React component like:
and some CSS in
./styles/button.css
of:After CSS Modules performs it's magic the generated CSS will be something like:
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:
Essentially all elements you need to style would receive a unique classname.
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.
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: