Skip to main content
React offers multiple ways to style your components. Each approach has its own benefits and use cases.

Styling Approaches

CSS Modules provide scoped CSS that won’t conflict with other components.

Import CSS Module

import cesese from './ItemCounter.module.css';

CSS Module File

.item-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
}

.item-text {
  width: 200px;
}

.color-red {
  color: yellow;
}

Using CSS Module Classes

<section className={cesese['item-row']}>
  <span className="item-text">{name}</span>
</section>
CSS Modules automatically scope class names to prevent conflicts. Use bracket notation cesese['item-row'] for class names with hyphens.

Complete Styling Example

Here’s a component using all three styling approaches:
import { useState } from "react";
import cesese from './ItemCounter.module.css';

interface Props {
  name: string;
  quantity?: number;
}

export const ItemCounter = ({ name, quantity }: Props) => {
  const [count, setCount] = useState(Number);

  const handleAdd = () => {
    setCount(count + 1);
  };

  const handleSub = () => {
    if (count === 0) return;
    setCount(count - 1);
  };

  return (
    <section 
      className={cesese['item-row']}
      // Commented out: alternative inline style approach
      // style={{
      //   display: 'flex',
      //   alignItems: 'center',
      //   gap: 10,
      //   margin: 10
      // }}
    >
      <span 
        className="item-text"
        style={{
          color: count === 0 ? 'red' : 'black',
        }}
      >
        {name}
      </span>
      <button onClick={handleAdd}>+1</button>
      <span>{count}</span>
      <button onClick={handleSub}>-1</button>
    </section>
  );
};

CSS Properties in JSX

1

Use camelCase

CSS property names become camelCase in JSX:
// CSS: background-color
// JSX: backgroundColor

style={{
  backgroundColor: 'red',
  borderRadius: 10
}}
2

Values are strings or numbers

Most values are strings. Numbers without units are treated as pixels.
style={{
  color: 'red',        // string
  padding: 10,         // number → 10px
  width: '100%',       // string with unit
  gap: 10              // number → 10px
}}
3

Use double braces

Inline styles use double braces: outer for JSX, inner for the object.
style={{ color: 'red' }}

Conditional Styling

Apply different styles based on state or props:

Conditional Colors

style={{
  color: count === 0 ? 'red' : 'black',
}}

Conditional Classes

className={isActive ? 'active-class' : 'inactive-class'}

Multiple Conditional Classes

className={`base-class ${isActive ? 'active' : ''} ${isLarge ? 'large' : ''}`}

CSS Modules vs Regular CSS

FeatureCSS ModulesRegular CSS
ScopeLocal to componentGlobal
Importimport styles from './file.module.css'import './file.css'
UsageclassName={styles.className}className="className"
ConflictsNo conflictsCan conflict
File name*.module.css*.css
CSS Modules require the .module.css file extension to work properly.

Best Practices

1

Use CSS Modules for component styles

CSS Modules prevent naming conflicts and keep styles scoped to components.
import styles from './Component.module.css';
2

Use inline styles for dynamic values

Inline styles are perfect for values that change based on state.
style={{ color: count === 0 ? 'red' : 'black' }}
3

Extract complex inline styles

For complex inline styles, create a variable:
const containerStyle = {
  display: 'flex',
  alignItems: 'center',
  gap: 10
};

<section style={containerStyle}>
4

Organize CSS files

Keep CSS files next to their components:
ItemCounter.tsx
ItemCounter.module.css

Common Flexbox Patterns

Horizontal Layout

.item-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
}

Fixed Width Text

.item-text {
  width: 200px;
}
Use flexbox (display: flex) with gap for spacing instead of margins between items. It’s cleaner and more maintainable.

Build docs developers (and LLMs) love