CSS Modules
1. Introduction to CSS Modules
What are CSS Modules?
CSS Modules is a CSS file in which all class names and animation names are scoped locally by default. It helps solve the problem of global CSS by automatically creating unique class names.
Key Benefits
- Local Scoping
- Avoiding Name Conflicts
- Explicit Composition
- Built-in with Create React App
- Works with Webpack and other build tools
2. Basic Syntax
Creating a CSS Module
/* Button.module.css */
.button {
padding: 10px 15px;
border-radius: 4px;
}
.primary {
background-color: #3498db;
color: white;
}
.secondary {
background-color: #f1f1f1;
color: #333;
}
Importing and Using in React
import React from 'react';
import styles from './Button.module.css';
function Button({ variant = 'primary', children }) {
return (
<button
className={`${styles.button} ${styles[variant]}`}
>
{children}
</button>
);
}
3. Advanced Styling Techniques
Composition
/* Typography.module.css */
.base {
font-family: Arial, sans-serif;
line-height: 1.5;
}
.heading {
composes: base;
font-weight: bold;
font-size: 24px;
}
.subtitle {
composes: base;
color: #666;
font-size: 16px;
}
Combining Multiple Classes
import styles from './Typography.module.css';
function Title() {
return (
<h1 className={`${styles.heading} ${styles.base}`}>
Welcome
</h1>
);
}
4. Conditional Styling
Dynamic Class Application
import React from 'react';
import styles from './Button.module.css';
function Button({ isActive, children }) {
return (
<button
className={`
${styles.button}
${isActive ? styles.active : styles.inactive}
`}
>
{children}
</button>
);
}
5. Global Styles
Using Global Selectors
/* global.module.css */
:global(.app-container) {
max-width: 1200px;
margin: 0 auto;
}
.localClass {
color: blue;
}
6. Composition with External Classes
Importing Classes from Another Module
/* Button.module.css */
.button {
padding: 10px 15px;
}
/* Theme.module.css */
.primaryTheme {
background-color: #3498db;
color: white;
}
/* Form.module.css */
.submitButton {
composes: button from './Button.module.css';
composes: primaryTheme from './Theme.module.css';
}
7. TypeScript Integration
Type-Safe CSS Modules
import styles from './Button.module.css';
interface Props {
className?: string;
}
const Button: React.FC<Props> = ({ className, children }) => {
return (
<button
className={`${styles.button} ${className}`}
>
{children}
</button>
);
}
8. Performance Considerations
Best Practices
- Keep CSS Modules small and focused
- Avoid deep nesting
- Use composition over complex inheritance
- Minimize the use of dynamic class names
9. Common Patterns
Responsive Design
.container {
width: 100%;
}
@media (min-width: 768px) {
.container {
width: 750px;
}
}
Handling Pseudo-classes
.button {
background-color: #3498db;
}
.button:hover {
background-color: #2980b9;
}
.button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
10. Webpack Configuration
Manual Setup
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.module\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
}
11. Common Mistakes to Avoid
- ❌ Don't use global styles extensively
- ❌ Avoid complex, deeply nested selectors
- ❌ Don't create too many small CSS modules
- ❌ Prevent overusing dynamic class names
Conclusion
CSS Modules provide a powerful, scoped approach to styling in React applications, solving many common CSS challenges while maintaining readability and performance.
Quick Reference
- ✅ Local Scoping
- ✅ Explicit Composition