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
| Approach | Scoped? | Notes |
|---|---|---|
| Plain CSS | No | Simplest, but risk of naming collisions |
| CSS Modules | Yes | Scoped automatically, still real CSS |
| Inline styles | Per-element | No pseudo-classes/media queries; useful for dynamic values |
| Tailwind CSS | N/A | Utility 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.