React CSS Modules

Scoped and modular CSS for React components

📦 What are CSS Modules?

CSS Modules are CSS files where class names are scoped locally by default. This prevents style conflicts and makes your components more maintainable by ensuring styles don't leak between components.


import styles from './Button.module.css';
                                    

Understanding CSS Modules

CSS Modules automatically generate unique class names for your styles, preventing naming conflicts across components. Each component can have its own styles without worrying about affecting other parts of your application. This approach combines the simplicity of CSS with the power of component-based architecture.

🔒

Scoped Styles

Styles are local to components

🎯

No Conflicts

Unique class names generated

📝

Regular CSS

Write normal CSS syntax

🔄

Reusable

Import and use anywhere

🔹 Creating a CSS Module

CSS Module files use the .module.css extension:

🔸 Button.module.css

.button {
  padding: 12px 24px;
  font-size: 16px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.3s;
}

.primary {
  background-color: #007bff;
  color: white;
}

.primary:hover {
  background-color: #0056b3;
}

.secondary {
  background-color: #6c757d;
  color: white;
}

.secondary:hover {
  background-color: #545b62;
}

🔸 Button.jsx

import styles from './Button.module.css';

function Button({ type = 'primary', children }) {
  return (
    <button className={`${styles.button} ${styles[type]}`}>
      {children}
    </button>
  );
}

// Usage
<Button type="primary">Primary Button</Button>
<Button type="secondary">Secondary Button</Button>

Output:

🔹 Multiple Classes

Combine multiple CSS Module classes:

🔸 Card.module.css

.card {
  background: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.title {
  font-size: 24px;
  color: #333;
  margin-bottom: 10px;
}

.content {
  color: #666;
  line-height: 1.6;
}

.highlighted {
  border-left: 4px solid #007bff;
  background-color: #f8f9fa;
}

🔸 Card.jsx

import styles from './Card.module.css';

function Card({ title, content, highlighted }) {
  const cardClass = highlighted 
    ? `${styles.card} ${styles.highlighted}`
    : styles.card;

  return (
    <div className={cardClass}>
      <h3 className={styles.title}>{title}</h3>
      <p className={styles.content}>{content}</p>
    </div>
  );
}

Output:

Card Title

This is a highlighted card with CSS Modules.

🔹 Composition

Reuse styles using the composes keyword:

🔸 Alert.module.css

.alert {
  padding: 15px;
  border-radius: 4px;
  margin-bottom: 10px;
  font-weight: 500;
}

.success {
  composes: alert;
  background-color: #d4edda;
  color: #155724;
  border: 1px solid #c3e6cb;
}

.error {
  composes: alert;
  background-color: #f8d7da;
  color: #721c24;
  border: 1px solid #f5c6cb;
}

.warning {
  composes: alert;
  background-color: #fff3cd;
  color: #856404;
  border: 1px solid #ffeaa7;
}

🔸 Alert.jsx

import styles from './Alert.module.css';

function Alert({ type, message }) {
  return (
    <div className={styles[type]}>
      {message}
    </div>
  );
}

// Usage
<Alert type="success" message="Success! Your changes were saved." />
<Alert type="error" message="Error! Something went wrong." />
<Alert type="warning" message="Warning! Please check your input." />

🔹 Global Styles in Modules

Use :global for styles that should not be scoped:

/* Component.module.css */

.container {
  padding: 20px;
}

/* This class will be global */
:global(.global-class) {
  color: red;
}

/* Mix local and global */
.container :global(.global-text) {
  font-weight: bold;
}

CSS Modules Benefits:

  • No naming conflicts: Unique class names automatically generated
  • Component-scoped: Styles only apply to their component
  • Easy to maintain: Styles live next to components
  • Standard CSS: Use regular CSS syntax you already know
  • Better performance: Only loads styles for used components

🔹 Naming Convention

Follow these naming patterns for CSS Modules:

  • File naming: ComponentName.module.css
  • Class naming: Use camelCase or kebab-case
  • Import naming: import styles from './Component.module.css'
  • Usage: className={styles.className}
// Good practices
import styles from './UserProfile.module.css';

<div className={styles.profileCard}>
  <h2 className={styles.userName}>John Doe</h2>
  <p className={styles.userBio}>Developer</p>
</div>

🧠 Test Your Knowledge

What file extension do CSS Modules use?