Skip to content

React Tutorial Styling React Applications

Component-Level Styling: Scoping and Theming in React

Lesson 87 of 156 2 min read By Deepak Paswan Updated Oct 10, 2026

Runnable lesson · press Try it on the examples to edit and run them here.

A component should carry its own look and be easy to reuse and delete. This lesson shows patterns for keeping styles at the component level, whichever tool you use.

The principle: one component, one block of styles

Keep the markup, the styles and the logic of a component together (in one folder, or one file for tiny ones). When you delete the component, you delete its styles, and no dead CSS remains.

code
PLAIN
src/components/Button/
├── Button.jsx
└── Button.module.css

Scope by naming

With plain CSS, give every component a root class and write all its rules under it. This is the idea behind BEM:

App.jsx
JSX
function App() {
  return (
    <div>
      <style>{`
        .user-card { display: flex; gap: 12px; align-items: center; padding: 12px; border: 1px solid #d0d7de; border-radius: 8px; max-width: 320px; }
        .user-card__avatar { width: 48px; height: 48px; border-radius: 50%; background: #1a5276; color: #fff; display: grid; place-items: center; font-weight: 700; }
        .user-card__name { margin: 0; font-size: 16px; }
        .user-card__role { margin: 0; font-size: 13px; color: #555; }
        .user-card--highlight { border-color: #e67e22; background: #fef5e7; }
      `}</style>
      <article className="user-card user-card--highlight">
        <div className="user-card__avatar" aria-hidden="true">AL</div>
        <div>
          <h3 className="user-card__name">Ada Lovelace</h3>
          <p className="user-card__role">Mathematician</p>
        </div>
      </article>
    </div>
  );
}

.user-card is the block, __avatar and __name are its parts, --highlight is a variant. Nothing outside .user-card is affected.

Theme with CSS variables

CSS custom properties inherit, so you can define a theme on a wrapper and every component below follows it. This is the best way to do light and dark mode:

App.jsx
JSX
function App() {
  const [theme, setTheme] = React.useState("light");

  return (
    <div className="app" data-theme={theme}>
      <style>{`
        .app { --bg: #ffffff; --text: #1c1b1f; --accent: #ca4b00; padding: 16px; background: var(--bg); color: var(--text); border-radius: 8px; }
        .app[data-theme="dark"] { --bg: #1c1b1f; --text: #f5f0ec; --accent: #ff9e6d; }
        .app .btn { background: var(--accent); color: var(--bg); border: 0; padding: 6px 14px; border-radius: 6px; cursor: pointer; }
      `}</style>
      <p>Theme demo: {theme} theme</p>
      <button className="btn" onClick={() => setTheme(theme === "light" ? "dark" : "light")}>Switch theme</button>
    </div>
  );
}

React changes only one attribute (data-theme). Colours, hover states and transitions are all handled by CSS, with no re-render of each styled element needed. If you must respect the user’s system setting, use @media (prefers-color-scheme: dark) for the default and the attribute for the manual switch.

Components that accept className

Let the parent adjust placement (margin, width) without editing the component, by merging a className prop:

App.jsx
JSX
function Box({ className = "", children }) {
  return <div className={("box " + className).trim()}>{children}</div>;
}

function App() {
  const merged = ("box " + "wide").trim();
  return (
    <div>
      <style>{`.box { padding: 12px; background: #eaf2f8; } .wide { max-width: 420px; }`}</style>
      <Box className="wide">Content</Box>
      <p>Merged classes: {merged}</p>
    </div>
  );
}

The component owns its inside look; the parent decides layout around it. Avoid letting parents reach into a component’s internals with deep selectors.

Where each kind of style lives

KindWhere
Design tokens: colours, spacing, font sizesCSS variables on :root in one global file
Reset and base element stylesOne global file imported once
Look of a componentCSS file or CSS Module beside the component
Layout between componentsThe parent’s CSS, or utility classes
Values computed at runtimeInline style or a CSS variable

Avoid these traps

  • Styling by tag name inside components (ul li a): fragile and global.
  • Increasing specificity to win a fight (!important, long selectors). Fix the naming or order instead.
  • Dead CSS that no component uses. Keeping styles beside components helps you find it.

Key points

  • Keep a component’s markup, logic and styles together; delete them together.
  • Scope with a root class (BEM) or CSS Modules; theme with CSS custom properties.
  • Let the parent control placement through a className prop, not the internals.