Component-scoped CSS is proper to avoid CSS class name clashes. React Js allows you to use CSS modules to work around this problem. You can use CSS modules in your React Js application if your react-scripts
version is 2.0 or higher.
What do CSS modules solve?
The issue we face using CSS is the class name conflicts. When you import the CSS file, the CSS classes defined in the CSS file become global. In other words, any CSS files imported into your component are visible throughout the application.
In the below example, I imported the Styles.css file in the SuccessMessage
component. I intended to limit classes in the Styles.css
only to the SuccessMessage
scope. But they are applied to all the elements in the application. That's not what I wanted.
Styles.css
.buttonClass {
background-color: green;
color: white
}
.spanClass {
color: rgb(11, 222, 85);
}
.divClass {
margin: 24px;
}
App.tsx
import SuccessMessage from "./components/SuccessMessage"
import ErrorMessage from "./components/ErrorMessage"
import { useState } from "react"
export const App = () => {
const [message, setMessage] = useState("success")
const toggleMessages = () => {
setMessage((prev) => {
return prev === "success" ? "error" : "success"
})
}
return(
<>
{message === "success" && <SuccessMessage/>}
{message === "error" && <ErrorMessage/>}
<div className="divClass"><button onClick={toggleMessages}>Show {message === "error" ? "Success" : "Error"} message</button></div>
</>
)
}
export default App
SuccessMessage component imports Styles.css
Importing Styles.css
to use locally. But the styles become global to the application.
import "../Styles.css"
const SuccessMessage = () =>{
return(
<div className="divClass">
<span className="spanClass">Your Account has been created successfully</span>
<br/>
<button className="buttonClass">Go to account</button>
</div>
)
}
export default SuccessMessage
ErrorMessage component
The ErrorMessage
component is also affected by the SuccessMessage
style imports. Note that the CSS classes for the button, span, and div also apply to this component's elements. But what if I want different styles in this component?
const ErrorMessage = () =>{
return(
<div className="divClass">
<span className="spanClass">We could not create your account</span>
<br/>
<button className="buttonClass">Contact customer service</button>
</div>
)
}
export default ErrorMessage
How to use CSS modules to limit the CSS scope
If your app uses react-scripts
version 2.0 or higher, you are all set to use CSS modules. The only change to consider is the naming convention of the CSS modules. It usually follows the [component].module.css
pattern. However, the module.css
is not optional.
In the below example, I have created two different CSS modules for SuccessMessage
and ErrorMessage
components. Then I import each module as styles. This way, the class names from Styles.css
are overridden by the class names from CSS modules. The components get the class names divClass
, buttonClass
, and spanClass
from their own CSS module with a unique class name.
SuccessMessage.module.css
.buttonClass {
background-color: green;
color: white
}
.spanClass {
color: rgb(11, 222, 85);
}
.divClass {
margin: 24px;
}
SuccessMessage component with CSS modules
import styles from "./SuccessMessage.module.css"
import "../Styles.css" //we have duplicate class names here
const SuccessMessage = () =>{
return(
<div className={styles.divClass}>
<span className={styles.spanClass}>Your Account has been created successfully</span>
<br/>
<button className={styles.buttonClass}>Go to account</button>
</div>
)
}
export default SuccessMessage
ErrorMessage.module.css
.buttonClass {
background-color: red;
color: white
}
.spanClass {
color: red;
}
.divClass {
margin: 24px;
}
ErrorMessage component with CSS modules
import styles from "./ErrorMessage.module.css"
const ErrorMessage = () =>{
return(
<div className={styles.divClass}>
<span className={styles.spanClass}>We could not create your account</span>
<br/>
<button className={styles.buttonClass}>Contact customer service</button>
</div>
)
}
export default ErrorMessage
CSS modules' dynamic class names
The usage of CSS classes is a little different. I use className={styles.buttonClass}
etc instead of className="buttonClass"
. This way, React Js generates a dynamic class name for each class name usage.
For example, the CSS class .divClass
will have different class names in each usage.
CSS modules enable CSS classes to scope to the component level. It allows us to solve CSS class name clashes by generating dynamic and unique class names.