Home Coding & Scripting Styling React Components Using CSS, CSS Modules, and More

Styling React Components Using CSS, CSS Modules, and More

264
0

Styling is one of the most important parts of building a good user experience in React. Components give structure and interactivity, but styling is what brings our UI to life. Many beginners start with plain CSS files and quickly notice challenges like class name clashes, deeply-nested styles becoming difficult to maintain, and accidental global overrides.

CSS Modules solve most of these pain points while still letting us write normal CSS. Meanwhile, modern CSS continues to evolve with new features like advanced selectors, custom properties, and improved scoping tools. In this post, we’ll learn how to use CSS and CSS Modules inside a React application in a simple and beginner-friendly way.


✔️ Prerequisites (If you plan to practice along)

Before diving in, we should already have a working React + TypeScript project created with Vite.

If not, please follow this post first: Creating Our First React App with TypeScript.

That post walks you through the setup and ensures our project includes files like:

  • index.html
  • src/main.tsx
  • src/App.tsx

These files are essential for understanding how React components work.


1. What Is CSS? (A Simple Explanation for Beginners)

Before learning to use CSS and CSS Modules with react — it’s important to know what CSS itself is.

CSS (Cascading Style Sheets) is a styling language used to control how HTML elements look on the screen.
HTML gives our page the structure (like headings, buttons, and paragraphs), and CSS adds the visual layer:

  • Colors
  • Fonts
  • Layout
  • Spacing
  • Animations
  • Responsiveness

Think of CSS like the “design rules” for your application.

Why is it called Cascading?

Because styles can come from multiple places (browser, global CSS file, component CSS file), and CSS decides which rule wins based on priority. This is called the cascade.

How CSS Works

We write rules using selectors like:

button {
  background-color: blue;
}

The browser reads them and applies these rules to matching elements.

Modern CSS Power

Modern CSS supports many new features, such as:

  • Custom properties (--primary-color)
  • New responsive layout tools
  • More powerful selectors
  • Better scoping techniques
  • Animations and transitions

These improvements make styling React components more flexible and maintainable.

CSS Modules build on this by giving us component-level isolation, preventing global style conflicts.


2. Why Styling Matters in React

When building UIs with React, we’ll eventually run into issues like:

  • Class name collisions (two components unintentionally using the same CSS class)
  • Styles leaking globally and affecting unrelated elements
  • Large CSS files becoming hard to maintain

CSS Modules help eliminate these problems. At the same time, modern CSS itself is becoming more powerful—new features like @property, new selectors, layout enhancements, and scoping mechanisms are now available, making styling more expressive and maintainable.


3. Styling Options in React

React supports a variety of styling approaches. Understanding them helps us choose the right one for our project.

a) Global CSS files

Simple .css files imported globally. Easy to start with, but can lead to conflicts as the project grows.

b) Inline styles / style objects

Passing style objects directly into components. Great for dynamic styles but limited for pseudo-classes (:hover, :active) and media queries.

c) CSS-in-JS libraries

Examples include styled-components and Emotion. Useful for heavy dynamic styling, theming, and runtime styles. They introduce an additional library layer.

d) CSS Modules

A balanced approach: write normal CSS but get scoped styles by default. This prevents global collisions and improves maintainability.

CSS Modules are especially strong for medium to large React applications because they combine familiarity (CSS syntax) with safety (isolated styling).


3. What Are CSS Modules?

CSS Modules are regular CSS files—named like ComponentName.module.css—that automatically scope their class names so they don’t conflict with anything else.

Example import:

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

Behind the scenes, our simple class names are transformed into unique names. This avoids conflicts and ensures our component “owns” its styles. For example, React (via Vite) transforms our class names as:

  • .button becomes something unique like Button_button__abc123
  • No two components ever share the same class name

Why CSS Modules Help

  • No global style collisions
  • Cleaner and safer refactoring
  • Full CSS support (media queries, animations, pseudo-classes)
  • Works perfectly with bundlers like Vite

Additionally, modern CSS features such as improved class selectors, advanced scoping, and custom properties make component-based styling even more powerful today.


4. Using CSS Modules With a Real Example (ToggleMessage Component)

The easiest way to understand CSS Modules is to learn them directly inside a real React component. We will take the simple ToggleMessage component we created in the post Understanding State Management in React and style it using CSS Modules, step-by-step.

by-step.


📁 Step 1: Original Component (Unstyled)

Here is the component we built earlier:

import { useState } from "react";

function ToggleMessage() {
  const [show, setShow] = useState(true);

  return (
    <div>
      <button onClick={() => setShow(!show)}>Toggle Message</button>

      {show && <p>Hello there!</p>}
    </div>
  );
}

export { ToggleMessage };

Right now, this works — but it has no styling.

Let’s style it properly using CSS Modules.


📁 Step 2: Create a Folder for the Component

We will keep each component and its CSS module inside its own folder because it keeps the component’s code and styles organized together, which becomes especially helpful as the project grows. However, this is not mandatory. This approach is often called the Component Folder Structure or the Component Encapsulation Pattern.

Inside our project, create files with following folder structure:

src/components/ToggleMessage/
  ToggleMessage.module.css
  ToggleMessage.tsx

🎨 Step 3: Add Styles in ToggleMessage.module.css

.container {
  padding: 16px;
  margin: 20px auto;
  max-width: 300px;
  text-align: center;
  border-radius: 8px;
  background: #f9f9f9;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.button {
  padding: 8px 14px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.2s;
}

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

.message {
  margin-top: 12px;
  font-size: 16px;
  color: #333;
  animation: fadeIn 0.3s ease-in-out;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

➡️ These classes (container, button, message) are scoped only to this component, thanks to CSS Modules.


⚛️ Step 4: Use the Styles in ToggleMessage.tsx

import { useState } from "react";
import styles from "./ToggleMessage.module.css";

function ToggleMessage() {
  const [show, setShow] = useState(true);

  return (
    <div className={styles.container}>
      <button
        className={styles.button}
        onClick={() => setShow(!show)}
      >
        Toggle Message
      </button>

      {show && <p className={styles.message}>Hello there!</p>}
    </div>
  );
}

export { ToggleMessage };

To style the component using a CSS Module, we added a few key updates:

  • We imported the CSS Module using
    import styles from "./ToggleMessage.module.css";
    This gives us a styles object containing all our class names.
  • We applied the styles using styles.className
    For example:
    • className={styles.container} styles the wrapping <div>
    • className={styles.button} styles the <button>
    • className={styles.message} styles the <p>
      These class names are automatically scoped to this component only.
  • In React, we use className instead of class because class is a reserved keyword in JavaScript. className works the same way as the HTML class attribute but is the correct way to apply CSS classes inside JSX.
  • The component now looks neater and more structured
    Each UI element is clearly assigned a style, making the component both readable and visually polished.
  • No styles leak into other components
    Because CSS Modules generate unique class names behind the scenes, this styling affects only this component.

This turns our original unstyled component into a clean, professional, reusable UI block.


🎉 What You Learned

By building this example, we now understand:

✔ What a CSS Module file is (*.module.css)
✔ How to import it into a component
✔ How class names become scoped and conflict-free
✔ How to build a styled component
✔ How React + Vite automatically supports CSS Modules

This single example teaches everything needed to start using CSS Modules in your projects.


5. Best Practices and Advanced Concepts

Use CSS Variables with Modules

Even in CSS Modules, we can use design tokens via CSS variables:

:root {
  --primary-color: #007bff;
}

Modules can reference them freely.


Compose or Combine Styles

You can combine classes easily:

className={`${styles.base} ${styles.primary}`}

Naming Conventions

Even though the final class names are scoped and hashed, keeping readable names like .container, .header, .title, .button makes your files cleaner.


Leverage Newer CSS Features

Modern CSS offers features such as:

  • Advanced selectors
  • @property for typed custom properties
  • Improved scoping
  • New layout capabilities

All of these work naturally inside CSS Modules.


When CSS Modules May Not Be Ideal

Consider CSS-in-JS libraries if you need:

  • Deep dynamic styles
  • Live theming
  • Runtime style generation

But for most React apps, CSS Modules provide a safer, simpler, and highly maintainable approach.


7. Summary

  • CSS Modules allow us to style components using standard CSS while preventing global conflicts.
  • A Vite + React + TypeScript project supports them without extra configuration.
  • They provide full CSS power including animations, pseudo-classes, media queries, variables, and new CSS features.
  • Use global CSS only for resets, typography, or variables.
  • Use CSS Modules for everything component-specific.

If you want, I can also create a starter template or show how to use SCSS Modules or theming with CSS variables.


🎁 Bonus Section 1 — What Is SCSS and How to Use SCSS Modules

🌟 What Is SCSS?

SCSS (Sassy CSS) adds capabilities such as:

  • Variables
  • Nesting
  • Functions (darken())
  • Mixins
  • Cleaner syntax

It compiles into normal CSS.


🔧 Install Sass

npm install sass

🎨 SCSS Module Example

$primary-color: #007bff;

.container {
  padding: 16px;
  background: #f9f9f9;
}

.button {
  background: $primary-color;

  &:hover {
    background: darken($primary-color, 10%);
  }
}

⚛️ Import SCSS Module

import styles from "./ToggleMessage.module.scss";

🎁 Bonus Section 2 — What Are Themes and How to Build Them

🌟 What Is a Theme?

A theme is a set of design values:

  • Background
  • Text color
  • Accent colors
  • Contrast
  • Typography

Examples:

  • Light mode
  • Dark mode
  • High-contrast mode

CSS variables make theme switching easy.


🎨 Step 1: Define Theme Variables

:root {
  --primary-color: #007bff;
  --background-color: #ffffff;
  --text-color: #333;
}

.dark-theme {
  --primary-color: #00bcd4;
  --background-color: #111;
  --text-color: #f1f1f1;
}

🎨 Step 2: Use Them in Modules

.container {
  background: var(--background-color);
  color: var(--text-color);
}

⚛️ Step 3: Toggle Themes

<div className={dark ? "dark-theme" : ""}>

🎁 Bonus Section 3 — CSS Frameworks (Bootstrap, Tailwind & Others)

📦 Bootstrap (Component-First CSS Framework)

Bootstrap is a classic, beginner-friendly CSS framework offering:

  • Prebuilt components (buttons, navbars, cards)
  • A responsive grid system
  • Utility classes (spacing, colors, typography)
  • Massive community and documentation

Used with React in two ways:

  1. Import CSS directly
  2. Use React-Bootstrap, which converts Bootstrap components into React components

Great for form-heavy UIs, prototypes, and admin dashboards.


🌟 Tailwind CSS (Utility-First Framework)

Tailwind provides tiny utility classes like:

  • p-4 → padding
  • bg-blue-500 → background color
  • rounded-md → border radius

Example:

<button className="px-4 py-2 bg-blue-500 text-white rounded-md">
  Click Me
</button>

Benefits:

  • Very fast development
  • No CSS files needed
  • Consistent design system

Trade-offs:

  • JSX becomes class-heavy
  • Some learning curve

✔ Other Utility/Atomic tools

Tachyons

Lightweight, early utility-first framework.

Windi CSS

Tailwind-compatible but faster.


🎁 Bonus Section 4 — Component Libraries (Styling Included)

These libraries ship fully styled, ready-to-use components.

Material UI (MUI)

  • Follows Google Material design
  • Very popular
  • Large component set

Chakra UI

  • Clean API
  • Simple dark mode support
  • “Style props” instead of CSS

Ant Design

  • Enterprise-grade components
  • Great for dashboards

Mantine

  • Modern, stylish
  • Excellent forms, modals, and hooks

Pros:

  • Huge productivity boost
  • Accessible and responsive
  • Theming built-in

Cons:

  • Less design flexibility
  • UI might look generic if not customized

📊 Comparison: CSS Modules vs SCSS vs Tailwind vs Bootstrap vs UI Libraries

FeatureCSS ModulesSCSS ModulesTailwindBootstrapComponent Libraries
Learning CurveEasyMediumMediumEasyMedium
Write CSS?YesYesNoNoNo
Custom Designs⭐ Full⭐ FullMediumLimitedLow
Speed of DevelopmentMediumMedium⭐ FastestFastVery Fast
Opinionated StylingLowLowMedium⭐ High⭐ Very High
ThemingManualManualBuilt-inPartialBuilt-in
Best ForClean, scoped CSSLarge appsRapid UI buildingSimple UIsDashboards & forms

References (Full Links)

https://www.cssscript.com/new-css-features/
https://codingkeeda.in/react-components-style-2025-guide/
https://en.wikipedia.org/wiki/CSS-in-JS
https://www.reacttutorial.com/css-modules-react
https://www.buttercups.tech/blog/css/styling-react-components-using-css-modules-a-complete-guide
https://www.sourcetrail.com/javascript/latest-developments-features-and-trends-in-react-for-2025/
https://moldstud.com/articles/p-css-modules-in-reactjs-essential-insights-every-developer-should-know

Previous articleUnderstanding Hooks in React and Common Hooks
Next articleUnderstanding Async and Promises in JavaScript
Heartin Kanikathottu
As a seasoned Cloud and Security Architect, I’ve led transformative initiatives in key roles, including Vice President at Morgan Stanley, Principal Architect at Societe Generale, and Tech Lead & Cloud Security Architect at VMware, among others. I’m also an internationally published author with multiple books available on platforms like Amazon and O'Reilly. Notably, one of my books was recognized as the 8th best cloud computing book of all time in 2020, reflecting the impact of my contributions to the field. With over 15 professional certifications from providers such as Microsoft (Azure), Amazon (AWS), Oracle (Java), Pivotal (Spring), and IBM, I bring a wealth of expertise to my work. Academically, I hold dual Master’s degrees in Cloud Computing and Data Analytics. I’m passionate about sharing knowledge and mentoring others, which is why I actively speak at global technical forums such as Tech Opportunities Fest at Platform Calgary, Google's Kubernetes Meetup, Java User Group, Elasticsearch Meetup, and the Agile India Conference.

LEAVE A REPLY

Please enter your comment!
Please enter your name here