A CSS class connects an element’s class name to rules in a stylesheet. In a React component, this keeps most styling in CSS while letting props choose which classes appear on the rendered element. It is a straightforward fit for predictable variants, though the component and stylesheet must agree on their names. section 7.3.3
Listing 7.3 src/Button.jsx with class names
import "./button.css"; #1
function Button({
children,
outline = false,
disabled = false,
className = "",
width = null,
}) {
const classNames = [ #2
"button", #3
outline ? "button--outline" : "", #4
className, #5
].filter(Boolean);
const style = width #6
? { width: `${width}px` } #6
: null;
return (
<button
className={classNames.join(" ")} #7
style={style} #7
disabled={disabled}
>
{children}
<svg
className="button__icon" #8
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
viewBox="0 0 490 490"
>
<polygon
points="240.112,0 481.861,245.004 240.112,490
8.139,490 250.29,245.004 8.139,0"
fill="currentColor"
/>
</svg>
</button>
);
}
export default Button;
The button always receives a base class, adds an outline class when requested, and accepts an application-provided class. Its variable width uses an inline style instead. section 7.3.3
Listing 7.4 src/button.css with class names
.button {
display: flex;
background: hotpink;
color: white;
border: 2px solid hotpink;
margin: 1em 2em;
padding: 1em 2em;
font-size: 120%;
width: 250px;
cursor: pointer;
gap: 10px;
justify-content: center;
align-items: center;
}
.button__icon {
width: 16px;
height: 16px;
position: relative;
}
.button:hover .button__icon { #1
animation: bounce .2s ease-in-out alternate infinite;
}
@keyframes bounce { #2
from {
left: 0;
}
to {
left: 10px;
}
}
.button--outline {
border-color: hotpink;
background-color: transparent;
color: hotpink;
}
.button:disabled { #3
opacity: 0.5;
pointer-events: none;
}
The stylesheet defines the base button, its icon and hover animation, an outline variant, and a disabled state using ordinary CSS. section 7.3.3
Application-specific styling can live in a separate stylesheet: an application passes `className="custom-button"`, while its CSS defines `.custom-button`. This preserves a distinction between reusable component styles and a local customization, but a misspelling on either side produces an unstyled button rather than a validation error. section 7.3.3
Choose classes with their operational trade-offs in mind:
- Plain CSS retains CSS features, is familiar to teams, and is inspectable in browser developer tools. With suitable bundling, component stylesheet imports and lazy-loaded components can limit which styles load; regular classes add no runtime calculation. section 7.3.4
- CSS and JSX are not synchronized: names can be misspelled, unused rules remain, and editing a component means moving between files. Globally reused names can collide across components or with a host website; naming conventions such as BEM reduce risk without guaranteeing isolation. section 7.3.5
- Use CSS files and class names readily in small or medium applications with limited styling complexity or dynamic values. Reconsider the approach as the application and team grow; CSS Modules and styled-components are alternatives to evaluate, not automatic upgrades. section 7.3.6 section 7.0




