Styling Approaches
React does not require one styling system.
You can use plain CSS, CSS Modules, CSS-in-JS, utility classes, component libraries, or a combination.
The right choice depends on team workflow, design system needs, bundle size, performance, and maintainability.
Common Options
| Approach | Strength | Watch Out For |
|---|---|---|
| Global CSS | simple and browser-native | naming conflicts and leakage |
| CSS Modules | scoped class names | still needs good composition habits |
| CSS-in-JS | props-driven styling and colocated styles | runtime cost and tooling complexity |
| Tailwind CSS | fast utility workflow | long class strings and design discipline |
| Bootstrap | quick prebuilt UI patterns | generic look and customization limits |
| Design system components | consistency | upfront investment |
You do not need to use every approach.
Most production apps standardize on one primary approach and a few supporting conventions.
Plain CSS
Plain CSS is still powerful.
.card {
border: 1px solid #d0d7de;
border-radius: 8px;
padding: 1rem;
}
.cardTitle {
font-size: 1.25rem;
margin: 0 0 0.5rem;
}function ProductCard({ product }) {
return (
<article className="card">
<h2 className="cardTitle">{product.name}</h2>
</article>
);
}The risk is that class names are global unless your tooling scopes them.
Inline Styles
Inline styles are useful for dynamic values that are truly calculated in JavaScript.
function ProgressBar({ value }) {
return (
<div className="progress">
<div className="progressFill" style={{ width: `${value}%` }} />
</div>
);
}Do not use inline styles for everything.
They cannot express pseudo-classes like :hover, media queries, or many accessibility states cleanly.
Conditional Classes
React styling often means choosing classes based on state.
function Button({ variant = "primary", disabled, children }) {
const className = `button button-${variant} ${disabled ? "button-disabled" : ""}`;
return (
<button className={className} disabled={disabled}>
{children}
</button>
);
}Libraries such as clsx can make this cleaner in real projects.
Responsive and Accessible Styling
Styling should support usability, not just appearance.
Check:
- keyboard focus is visible
- text has enough contrast
- layout works on small screens
- clickable targets are large enough
- motion respects reduced-motion preferences
- disabled controls look disabled and are actually disabled
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms;
scroll-behavior: auto;
}
}Common Mistakes
- Choosing a styling tool before defining design constraints.
- Using inline styles for hover, focus, and responsive behavior.
- Forgetting accessible focus states.
- Creating one-off styles instead of reusable design tokens.
- Mixing many styling systems without clear boundaries.
Which styling concern is accessibility-related?
Practical Challenge
Take a simple Button component and define:
- primary and secondary variants
- disabled styling
- visible focus styling
- responsive spacing
Implement it using plain CSS first, then discuss how CSS Modules or Tailwind would change the implementation.
Recap
React styling is about choosing a maintainable system for the product.
Prioritize consistency, accessibility, responsive behavior, and team clarity over chasing a fashionable tool.