className
Set an element's CSS classes; JSX uses className because class is reserved in JavaScript.
<div className={string} />Parameters
| Parameter | Type | Description |
|---|---|---|
$classNameoptional | string | A space-separated list of CSS class names. Works like the class attribute in HTML; React uses the DOM property name. |
JSX compiles to JavaScript, where class is a reserved word, so React exposes the DOM property name className instead. It takes one string containing every class, space separated.
When to reach for it
- Essentially all styling. Static rules belong in a stylesheet keyed by class; that is cheaper for the browser than inline styles and gives you pseudo-classes, media queries and cascade.
- Leave
stylefor values that genuinely come from JavaScript at runtime.
What trips people up
Writing class= is the classic slip — React logs Invalid DOM property `class`. Did you mean `className`? in development. Since React 16 it warns but still passes the attribute through to the DOM, so the styling usually does apply and the warning is easy to ignore; className is the canonical name and the only one React will keep supporting.
It is one string, not a list. Concatenating conditions by hand produces double spaces and stray undefined text, which is why almost every codebase ends up with a tiny helper or the clsx package.
There is no merging. If you spread props onto an element and also write className, whichever appears last in the JSX wins and the other is discarded — a common cause of a design-system component ignoring the class a caller passed. Accept className explicitly and join it with your own.
SVG elements are the one exception: React accepts className there too, so you never need class.
Example
When to use it
- Toggling an active class on the selected tab
- Applying a variant class such as button-primary from a prop
- Letting callers extend a shared component's styling from outside
- Adding an error class to a field that failed validation
Frequently asked questions
Why doesn't class work in React?
Because class is a reserved word in JavaScript and JSX compiles to JavaScript, so React named the prop className after the DOM property. React warns "Invalid DOM property `class`. Did you mean `className`?" in development — but since React 16 it warns and still passes the attribute through to the DOM, so the styles usually do apply. Use className anyway: it is the canonical name React documents and supports.
How do I apply a class conditionally?
Build the string with a ternary or an array join: className={isActive ? "tab tab-active" : "tab"}. For more than a couple of conditions use clsx or classnames, which drop falsy entries for you.
Should I use className or style?
Use className for anything that can be expressed in a stylesheet, and style only for values computed at runtime, such as a width derived from state. Classes give you hover, media queries and caching that inline styles cannot.
More examples
Building the string with clsx
clsx skips falsy values and object keys whose value is false, so the first button gets "btn btn-primary btn-block" and the second gets "btn btn-secondary btn-disabled mt-2" — no double spaces, no literal "false" or "undefined" in the attribute. Note the caller's className is passed last so it can override, and that variant is interpolated with a template literal, not string-concatenated inside quotes.
import clsx from "clsx";
function Button({ variant = "secondary", disabled, fullWidth, className }) {
return (
<button
disabled={disabled}
className={clsx(
"btn",
`btn-${variant}`,
{ "btn-block": fullWidth, "btn-disabled": disabled },
className
)}
>
Save
</button>
);
}
export default function Toolbar() {
return (
<div>
<Button variant="primary" fullWidth />
<Button disabled className="mt-2" />
</div>
);
}CSS Modules
With CSS Modules the import gives you an object mapping your authored names to hashed, file-scoped ones, so className is set from a variable rather than a literal. Two classes are combined with a template literal. The names are generated at build time, which is why a typo like styles.titel fails silently as undefined instead of erroring — the element simply renders unstyled.
import styles from "./Card.module.css";
export default function Card() {
return (
<div className={styles.card}>
<h4 className={styles.title}>Scoped styling</h4>
<p className={`${styles.body} ${styles.muted}`}>
styles.card is a generated string like "Card_card__3xK1p".
</p>
</div>
);
}
Discussion