React Styling Components
React does not enforce one way to style components — it gives you several options. Each approach suits different project sizes and team preferences. This topic covers the most common styling methods from the simplest to the most structured, so you can pick the right tool for your project.
Method 1: Inline Styles
Inline styles in React use a JavaScript object, not a CSS string. Property names use camelCase instead of kebab-case.
function Alert({ message, type }) {
const style = {
padding: "12px 16px",
borderRadius: "4px",
color: type === "error" ? "red" : "green",
backgroundColor: type === "error" ? "#ffe0e0" : "#e0ffe0",
fontWeight: "bold",
};
return <div style={style}>{message}</div>;
}
CSS vs JSX style property names
CSS JSX
----------------------------
font-size fontSize
background-color backgroundColor
border-radius borderRadius
text-align textAlign
margin-top marginTop
Inline styles work well for dynamic styles that depend on props or state. Avoid them for large, complex components because they mix structure and presentation.
Method 2: External CSS Files
Import a regular .css file into your component. All class names from the file become available globally.
/* Button.css */
.btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.btn-primary {
background-color: blue;
color: white;
}
.btn-secondary {
background-color: gray;
color: white;
}
/* Button.jsx */
import "./Button.css";
function Button({ label, variant = "primary" }) {
return (
<button className={`btn btn-${variant}`}>
{label}
</button>
);
}
External CSS is familiar and works immediately. The downside: class names are global — a class named .btn in one file can conflict with a class named .btn in another file.
Method 3: CSS Modules
CSS Modules solve the global naming conflict problem. File names end with .module.css. React automatically scopes class names to the component that imports them.
/* Button.module.css */
.btn {
padding: 10px 20px;
cursor: pointer;
}
.primary {
background: blue;
color: white;
}
/* Button.jsx */
import styles from "./Button.module.css";
function Button({ label }) {
return (
<button className={`${styles.btn} ${styles.primary}`}>
{label}
</button>
);
}
The actual class name in the browser becomes something like Button_btn_x7k2q — unique and impossible to conflict with other components.
Method 4: Conditional Class Names
Apply different class names based on state or props using template literals or ternary operators.
function NavLink({ label, isActive }) {
return (
<a className={isActive ? "nav-link active" : "nav-link"}>
{label}
</a>
);
}
// Or using template literals
function NavLink({ label, isActive, isDisabled }) {
const className = [
"nav-link",
isActive ? "active" : "",
isDisabled ? "disabled" : "",
].filter(Boolean).join(" ");
return <a className={className}>{label}</a>;
}
The classnames library (popular shortcut)
import classNames from "classnames";
const cls = classNames("nav-link", {
active: isActive,
disabled: isDisabled,
});
// Result: "nav-link active" when isActive=true, isDisabled=false
Method 5: Tailwind CSS
Tailwind provides utility classes that you apply directly in JSX. Each class does one specific thing — there is no separate CSS file to manage.
function Card({ title, body }) {
return (
<div className="p-4 rounded-lg shadow-md bg-white border border-gray-200">
<h3 className="text-xl font-bold text-gray-800 mb-2">{title}</h3>
<p className="text-gray-600 text-sm">{body}</p>
</div>
);
}
Tailwind eliminates naming classes and writing CSS from scratch. It works especially well with component-based frameworks like React because each component controls its own Tailwind classes.
Method 6: Styled Components (CSS-in-JS)
Styled components let you write actual CSS inside JavaScript using template literals. They create a new React component that comes pre-styled.
import styled from "styled-components";
const Button = styled.button`
padding: 10px 20px;
background: ${(props) => (props.primary ? "blue" : "gray")};
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
`;
function App() {
return (
<div>
<Button>Default</Button>
<Button primary>Primary</Button>
</div>
);
}
Styled components support dynamic styles via props, auto-scope class names, and keep styles collocated with the component that uses them.
Choosing a Styling Method
Scenario Recommended Approach
------------------------------------------------------------
Quick prototype or small project Inline styles or CSS file
Component library or large app CSS Modules or Tailwind
Design system with dynamic theming Styled Components or Tailwind
Joining an existing project Match what is already there
Global Styles in React
Import a global CSS file in your app's entry point (main.jsx or index.js) for styles that apply across the entire app — like resets, typography defaults, and CSS custom properties.
/* main.jsx */
import "./global.css"; // Imports once, applies everywhere
import App from "./App";
Summary
React supports multiple styling approaches. Inline styles handle dynamic values tied to props or state. External CSS files bring familiar stylesheet workflow but risk global name conflicts. CSS Modules solve naming conflicts by automatically scoping class names. Conditional class names let styles respond to component state. Tailwind CSS offers utility classes applied directly in JSX. Styled components write CSS inside JavaScript with full prop-based dynamic styling. Most projects settle on one primary approach — pick one that matches your team's skill set and project complexity.
