React CSS Styling

React supports several ways to style components, from quick inline styles to fully scoped CSS Modules.

Inline Styles with the style Prop

The style prop accepts a JavaScript object, not a CSS string, so property names are camelCase (backgroundColor, not background-color) and numeric values are treated as pixels unless the property is unitless. Inline styles are handy for one-off, dynamic values computed at render time, but they can't use pseudo-classes like :hover or media queries.

A Dynamically Colored Alert

function AlertBox({ message = 'This is an alert', isUrgent = true }) {
  const style = {
    padding: 12,
    borderRadius: 4,
    backgroundColor: isUrgent ? '#fdecea' : '#eef6ff',
    color: isUrgent ? '#b00020' : '#0b4a8f',
    fontWeight: isUrgent ? 'bold' : 'normal',
  };

  return <div style={style}>{message}</div>;
}

export default AlertBox;

External Stylesheets and className

For most static styling, a plain CSS file imported once and applied through the className prop is simpler and supports the full range of CSS features, including hover states, animations, and media queries. Because the styles live in a regular .css file, they're global by default — a class name like .card can clash with a class of the same name defined elsewhere in the app.

Styling with an Imported Stylesheet

// NOTE: The original lesson imports a separate "./Card.css" file
// (import './Card.css';). This sandbox only runs a single file, so the same
// CSS is embedded here via a <style> tag instead — the className usage below
// is otherwise identical to importing a real stylesheet.
function Card({ title, children }) {
  return (
    <div className="card">
      <style>{`
        .card { border: 1px solid #ddd; border-radius: 8px; padding: 16px; }
        .card-title { margin: 0 0 8px; font-size: 1.1rem; }
        .card-body { color: #444; }
      `}</style>
      <h3 className="card-title">{title}</h3>
      <div className="card-body">{children}</div>
    </div>
  );
}

function App() {
  return (
    <Card title="Card Title">
      <p>This is the card body, styled with className and a plain stylesheet.</p>
    </Card>
  );
}

export default App;
Note: Class names in a plain imported stylesheet are global across the whole bundle. Namespacing prefixes like .card-title (rather than just .title) help avoid accidental collisions between components.

CSS Modules for Scoped Styles

A CSS Module is a stylesheet named with a .module.css suffix that the build tool compiles into locally-scoped class names, automatically rewriting each one to something unique like card_title_a3f1x. You import it as a JavaScript object and reference classes as properties, which also gives you a compile error if you typo a class name.

Scoped Styling with a CSS Module

// NOTE: The original lesson imports a "./Card.module.css" CSS Module
// (import styles from './Card.module.css';), which requires a build-tool
// loader that isn't available in this single-file sandbox. The "styles"
// object a CSS Module import would normally give you is simulated below with
// a plain object, so the className={styles.card} usage stays identical to
// the real CSS Modules pattern.
const styles = {
  card: 'card',
  cardTitle: 'card-title',
  cardBody: 'card-body',
};

function Card({ title, children }) {
  return (
    <div className={styles.card}>
      <style>{`
        .card { border: 1px solid #ddd; border-radius: 8px; padding: 16px; }
        .card-title { margin: 0 0 8px; font-size: 1.1rem; }
        .card-body { color: #444; }
      `}</style>
      <h3 className={styles.cardTitle}>{title}</h3>
      <div className={styles.cardBody}>{children}</div>
    </div>
  );
}

function App() {
  return (
    <Card title="Card Title">
      <p>Styled through an object shaped like a CSS Module import.</p>
    </Card>
  );
}

export default App;
ApproachScopeBest For
Inline style propSingle element, that render onlyDynamic, computed-at-runtime values
External stylesheet + classNameGlobalSmall apps, quick prototypes, shared design classes
CSS ModulesLocal to the importing componentMedium-to-large apps where name collisions matter
  • Reach for inline styles only when a value must be computed from props or state at render time.
  • Use a plain stylesheet for genuinely global rules like resets, typography, and CSS variables.
  • Prefer CSS Modules for component-specific styling once a project has more than a handful of components.
  • Whatever approach you pick, stay consistent within a project so styles are predictable to find.

Exercise: React CSS Styling

How must property names be written inside a React inline style object?