DevAcademy
LearnReactStyling in React
BeginnerReact

Styling in React

Learn the main approaches to styling React components: plain CSS files, CSS Modules, and inline styles.

Reading Time

14 min

Lesson

Lesson 11 of 42

React Doesn’t Prescribe a Styling Method

Unlike some frameworks, React has no built-in styling system — you’re free to use plain CSS, CSS Modules, CSS-in-JS libraries, or utility frameworks like Tailwind CSS.

Plain CSS Files

The simplest approach: write a regular .css file, import it into your component, and use className to apply classes — exactly like styling any other HTML page.

Importing a Plain CSS File

// Button.css
// .btn { padding: 8px 16px; border-radius: 6px; }

import "./Button.css";

function Button({ label }) {
  return <button className="btn">{label}</button>;
}

Plain CSS Has No Scoping

A plain imported CSS file is global — a class name like .card can accidentally collide with the same class name used in a completely different component elsewhere in the app.

CSS Modules

A CSS Module (a file named *.module.css) scopes class names automatically to the component that imports it, avoiding naming collisions entirely.

Using a CSS Module

// Button.module.css
// .btn { padding: 8px 16px; border-radius: 6px; }

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

function Button({ label }) {
  return <button className={styles.btn}>{label}</button>;
}
// The class name is compiled to something unique, like "Button_btn__a1b2c"

Inline Styles

The style prop accepts a JavaScript object, not a CSS string — property names are camelCase, and numeric values are treated as pixels by default.

Inline Styles Example

function Box() {
  return (
    <div
      style={{
        padding: 16,
        backgroundColor: "steelblue",
        borderRadius: 8,
      }}
    >
      Styled inline
    </div>
  );
}

Conditional Class Names

Template literals or a small helper (like the popular clsx library) make it easy to apply classes conditionally based on props or state.

Conditional Classes

function Alert({ type, message }) {
  return (
    <div className={`alert alert-${type}`}>
      {message}
    </div>
  );
}

<Alert type="error" message="Something went wrong" />;
// renders className="alert alert-error"

Comparing Approaches

ApproachScoped?Notes
Plain CSSNoSimplest, but risk of naming collisions
CSS ModulesYesScoped automatically, still real CSS
Inline stylesPer-elementNo pseudo-classes/media queries; useful for dynamic values
Tailwind CSSN/AUtility classes composed directly in JSX

Best Practice

Reach for inline styles only for values that must be computed dynamically at runtime (like a progress bar’s width). For everything else, prefer CSS Modules or a utility framework — they support pseudo-classes and media queries that inline styles cannot.

Interview Questions

Quick Quiz

1. What is the main advantage of CSS Modules over plain imported CSS?

2. What type of value does the style prop expect?

3. Why are inline styles a poor fit for hover effects and media queries?