React CSS Styling

In the React ecosystem, there isn't just "one way" to handle styles. Because React focuses on components, styling often shifts from global stylesheets to component-specific logic. Choosing the right approach depends on the size of your project, the need for dynamic styles, and your team's preference for keeping CSS and JavaScript separate or unified.

Styling Approaches in React

1. Inline Styles

  • Apply styles directly in JSX using JavaScript objects rather than strings.
  • Properties must be camelCased (e.g., backgroundColor instead of background-color).
  • Useful for styles that depend on a component's state or props.
Common Mistake: Forgetting that inline styles in React are objects. Beginners often try to write style="color: red;" like in standard HTML, but React requires style={{ color: 'red' }}.

2. CSS Modules

  • Use CSS Modules to scope styles locally to a specific component automatically.
  • By naming a file filename.module.css, your build tool (like Vite or Webpack) will generate unique class names, preventing "class name collisions" where styles from one component accidentally affect another.
Developer Tip: CSS Modules are the "sweet spot" for many teams. They allow you to write plain CSS while ensuring that a class name like .btn in Component A won't break the .btn in Component B.

3. Styled Components

  • Create styled components with the styled-components library using tagged template literals.
  • This approach bridges the gap between CSS and JS, allowing you to pass props directly into your CSS logic to change colors, sizes, or visibility dynamically.
Best Practice: When using Styled Components, define your styled elements outside of the main component function. Defining them inside the function causes the component to be re-created on every render, which hurts performance.

4. CSS-in-JS Libraries (Emotion)

  • Utilize CSS-in-JS libraries like Emotion, which are very similar to Styled Components but often offer more flexibility with the css prop.
  • Provides a high-performance, dynamic way to write styles that can be calculated at runtime.

5. Global Styles

  • Apply global styles using standard .css files imported at the root of your application (usually main.jsx or App.jsx).
  • Perfect for CSS resets, typography defaults, and global layout variables (like CSS variables for brand colors).
Watch Out: Relying too heavily on global styles in a large React app can lead to "specificity wars," where you have to use !important to override styles because you aren't sure where the original style is coming from.

6. Theming with Styled Components

  • Implement theming using a ThemeProvider wrapper.
  • This is the industry standard for implementing Dark Mode or multi-brand support, as it injects a "theme" object into every styled component in your app.

Examples for each of these approaches:

Inline Styles

Inline styles are best for values that change frequently, such as a progress bar width or a user-selected color.

import React from 'react';

const InlineStyleComponent = () => {
  // Styles are written as a standard JS object
  const style = {
    color: 'blue',
    fontSize: '16px',
    fontWeight: 'bold',
    marginTop: '20px' // Use camelCase for properties
  };

  return (
    
This component uses a JavaScript object for styling.
); }; export default InlineStyleComponent;

CSS Modules

To use CSS Modules, ensure your file ends in .module.css. This tells React to treat the classes as local variables.

// styles.module.css
.moduleComponent {
  color: green;
  font-size: 18px;
  padding: 1rem;
  border: 1px solid #ccc;
}

// ModuleStyleComponent.jsx
import React from 'react';
import styles from './styles.module.css';

const ModuleStyleComponent = () => {
  return (
    
This class name is automatically scoped to this component.
); }; export default ModuleStyleComponent;

Styled Components

Styled Components allow you to create "UI primitives" that carry their own styles. This makes your JSX look much cleaner.

import React from 'react';
import styled from 'styled-components';

// This creates a 'div' element with these styles attached
const StyledContainer = styled.div`
  color: purple;
  font-size: 20px;
  padding: 20px;
  border-radius: 8px;
  background: #f9f9f9;

  &:hover {
    background: #eee; // Easy nesting like Sass!
  }
`;

const StyledComponentExample = () => {
  return (
    
      This is a component built with styled-components.
    
  );
};

export default StyledComponentExample;

CSS-in-JS Libraries (Emotion)

Emotion is highly versatile. In this example, we use the css prop to define styles directly on an element.

import React from 'react';
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';

const cardStyle = css`
  background-color: #fffbe6;
  padding: 15px;
  border-left: 5px solid #ffe58f;
  border-radius: 4px;
`;

const EmotionStyledComponent = () => {
  return (
    
This component uses Emotion's css prop for styling.
); }; export default EmotionStyledComponent;

Global Styles

Global styles are typically used for "resetting" the browser's default behavior or setting base fonts.

// styles.css
body {
  margin: 0;
  font-family: 'Inter', sans-serif;
  background-color: #f0f0f0;
}

h1 {
  color: #333;
}

// App.jsx
import React from 'react';
import './styles.css'; // Import once at the top level

const App = () => {
  return (
    

Main Application

Global styles are applied throughout the whole app.

); }; export default App;

Theming with Styled Components

Theming is incredibly powerful for maintaining consistency. By defining colors in one place, you can change your entire app's look by updating a single object.

import React from 'react';
import styled, { ThemeProvider } from 'styled-components';

// 1. Define your design tokens
const theme = {
  primaryColor: '#3498db',
  secondaryColor: '#2ecc71',
  fontFamily: 'Arial, sans-serif'
};

// 2. Access tokens via props.theme
const ThemedButton = styled.button`
  color: white;
  background-color: ${props => props.theme.primaryColor};
  font-family: ${props => props.theme.fontFamily};
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  cursor: pointer;

  &:hover {
    background-color: ${props => props.theme.secondaryColor};
  }
`;

const ThemedApp = () => {
  return (
    // 3. Wrap your app in the ThemeProvider
    
      
Themed Button
); }; export default ThemedApp;
Developer Tip: For real-world projects, developers often combine Global Styles (for basics) with either CSS Modules or Styled Components (for component logic). There is no need to pick just one—use the tool that makes the most sense for the task!