CSS Modules provide a way to write CSS that is scoped to a single React component instead of being global.
Each component imports its own .module.css file, and the build system generates unique class names so styles never clash between components.
This helps you build clean, maintainable, and truly component-based UIs without worrying about global CSS conflicts.
.title are transformed into unique ones such as:
// Example of a compiled CSS Module class name
card__title__3H8sd
styles)..module.css to be treated as CSS Modules.Card.module.css.import styles from "./Card.module.css";className={styles.className}.styles.Here’s a simple Card component styled using Card.module.css.
// Card.module.css - styles local to the Card component
.card {
background-color: #f8f9fa;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.title {
color: #007bff;
margin-bottom: 10px;
}
.text {
color: #555;
}
// Card.js - React component using the Card.module.css styles
import React from "react";
import styles from "./Card.module.css";
function Card() {
return (
<div className={styles.card}>
<h3 className={styles.title}>CSS Modules Example</h3>
<p className={styles.text}>
This card is styled with scoped CSS using modules.
</p>
</div>
);
}
export default Card;
Each CSS class (card, title, text) becomes a property on the imported styles object, and React uses the generated unique class names in the DOM.
You can dynamically toggle or combine class names using state and template literals (or utilities like classnames).
// Button.js - toggling CSS Module classes using component state
import React, { useState } from "react";
import styles from "./Button.module.css";
function Button() {
const [active, setActive] = useState(false);
return (
<button
className={`${styles.button} ${active ? styles.active : ""}`}
onClick={() => setActive(!active)}
>
{active ? "Active" : "Inactive"}
</button>
);
}
export default Button;
// Button.module.css - base and active styles for the button
.button {
padding: 10px 20px;
border: none;
color: white;
border-radius: 4px;
background-color: #6c757d;
}
.active {
background-color: #28a745;
}
This pattern lets you keep styles scoped while still reacting to component state (like hovered, active, or selected UI states).
When the Card component is rendered:
<div> gets a unique class (for example Card_card__1AbcD) that applies the card layout and shadow.When the Button component is rendered:
styles.button is applied (grey background).active state, which adds styles.active on top of the base class.In browser DevTools, you’ll see long, hashed class names instead of plain .button or .card, confirming that CSS Modules are scoping your styles.
.module.css to be treated as CSS Modules.styles.card, styles.title..css files stay global until you rename them to use the .module.css convention.A typical folder structure might look like this:
// Example folder structure using CSS Modules
? src/
┣ ? components/
┃ ┣ ? Card.js
┃ ┣ ? Card.module.css
┃ ┣ ? Button.js
┃ ┗ ? Button.module.css
┗ ? App.js
Card.js and Card.module.css in the same folder)..cardTitle instead of generic ones like .title for readability.ProfileCard and style it using ProfileCard.module.css.active and inactive, and toggle them using React state.active and inactive, and confirm that the styles remain scoped and do not conflict.Goal: Practice using CSS Modules to build scoped, component-based styling in React and verify that styles don’t leak across components.