CSS Modules for Scoped Styles in React JS

CSS Modules are a popular technique for scoping styles in React applications. They allow you to write traditional CSS but ensure that the styles are scoped to the specific component, avoiding conflicts with other components' styles. This approach is ideal for large applications where managing global CSS can become challenging. In this article, we’ll explore how to use CSS Modules in React, along with examples of how they work.

1. What are CSS Modules?

CSS Modules allow you to write CSS in a way that automatically scopes the styles to the specific component. Instead of writing global styles that apply to elements throughout the entire application, CSS Modules generate unique class names that are locally scoped. This ensures that styles don't unintentionally apply to other parts of the application, leading to cleaner and more maintainable code.

2. Setting Up CSS Modules in React

To use CSS Modules in React, you first need to create a CSS file with a special naming convention. By default, React’s create-react-app supports CSS Modules out of the box. The key difference is the file extension: instead of a traditional style.css, the file should have the .module.css extension.

Example 1: Basic Setup

Let’s create a simple React component and apply scoped styles using CSS Modules.

        
          // App.module.css
          .container {
            background-color: lightblue;
            padding: 20px;
            text-align: center;
          }

          .heading {
            color: darkblue;
          }
        
      
        
          // App.js
          import React from 'react';
          import styles from './App.module.css'; // Import the CSS Module

          const App = () => {
            return (
              

Hello, CSS Modules!

); }; export default App;

In this example, the App.module.css file contains the scoped styles, and the CSS classes are imported as a JavaScript object using the import styles statement. The classes are then applied by referencing the keys of the styles object in the JSX, ensuring that these styles are scoped to the App component.

3. How CSS Modules Work

When you import a CSS Module, React automatically generates unique class names for each CSS class. This prevents class name collisions by ensuring that each class is specific to the component it’s used in.

Example 2: Generated Unique Class Names

Suppose you have the following CSS:

        
          // Button.module.css
          .button {
            background-color: red;
            color: white;
            padding: 10px;
          }
        
      
        
          // Button.js
          import React from 'react';
          import styles from './Button.module.css';

          const Button = () => {
            return (
              
            );
          };

          export default Button;
        
      

The class button in the Button.module.css file is scoped to the Button component. When the app is built, React will automatically change the class name to something like Button_button__xyz12 to ensure it doesn’t conflict with other components.

4. Benefits of Using CSS Modules

  • Scoped Styles: CSS Modules ensure that styles are scoped to the component, preventing global styles from accidentally overriding them.
  • Maintainability: By using CSS Modules, you reduce the risk of name collisions and make the codebase easier to maintain, as styles are encapsulated within each component.
  • Cleaner Components: The separation of styles from logic allows components to be cleaner and more focused on their functionality.
  • Modularity: Styles are modularized by component, which makes it easier to reuse and update styles without affecting other parts of the application.

5. Working with Dynamic Styles

You can also combine dynamic values with CSS Modules by using JavaScript expressions to manipulate class names based on props or state.

Example 3: Dynamic Class Names

        
          // Button.module.css
          .primary {
            background-color: blue;
          }

          .secondary {
            background-color: gray;
          }
        
      
        
          // Button.js
          import React, { useState } from 'react';
          import styles from './Button.module.css';

          const Button = () => {
            const [isPrimary, setIsPrimary] = useState(true);

            const buttonClass = isPrimary ? styles.primary : styles.secondary;

            return (
              
            );
          };

          export default Button;
        
      

In this example, the Button component toggles between two styles (primary and secondary) based on the component’s state. The appropriate class is applied dynamically using a conditional expression.

6. Limitations of CSS Modules

  • No Global Styles: CSS Modules are scoped to individual components, which means that global styles (such as those for layouts or third-party libraries) still need to be handled with regular CSS or another styling solution.
  • No Pseudo-Classes or Pseudo-Elements: While CSS Modules are great for scoped styles, they do not allow the use of pseudo-classes (like :hover) or pseudo-elements (like ::before). For such cases, you may need to use regular CSS or a CSS-in-JS solution.
  • Overhead in Setup: Although React’s create-react-app supports CSS Modules out of the box, setting up CSS Modules in custom Webpack or build configurations can add additional complexity.

7. Conclusion

CSS Modules provide a powerful and efficient way to scope styles to individual React components. This technique solves many of the issues related to global CSS, such as class name collisions and unintentional style overrides. While CSS Modules work well for component-specific styling, they do have some limitations, such as the inability to apply global styles or pseudo-classes. For complex applications, CSS Modules are a great choice for managing styles in a modular, maintainable, and scalable way.





Advertisement