Share
1

Styling in React: Approaches to Beautiful Components

by ObserverPoint · June 30, 2025

You’ve mastered the core React concepts and Hooks; now it’s time to make your components look good! While React focuses on the logic and structure of your UI, CSS (as we’ve discussed) handles its presentation. The challenge in a component-based architecture like React is how to effectively manage and apply styles in a way that is maintainable, scalable, and avoids conflicts between components. This article will explore several popular approaches to styling your React applications, ranging from simple inline styles to more advanced solutions like CSS Modules and Styled Components, with a brief mention of popular CSS frameworks.

Choosing the right styling approach depends on your project’s size, team preferences, and the level of customization required. Each method has its pros and cons regarding maintainability, performance, and developer experience. Understanding these different techniques will equip you to make informed decisions for your React projects, ensuring your UIs are both functional and visually appealing.

Inline Styles: Quick & Component-Local

The simplest way to style an element in React is using inline styles. This approach involves passing a JavaScript object where keys are camelCased CSS property names and values are strings representing the property values. It’s similar to HTML inline styles but uses JavaScript objects instead of CSS strings.

Pros:

  • Component-local by default: Styles are directly tied to the component, avoiding global CSS conflicts.
  • Dynamic styling: Easy to apply styles based on component state or props.
  • No additional setup required.

Cons:

  • Lacks CSS features: No pseudo-classes (`:hover`, `:active`), pseudo-elements (`::before`), media queries, or keyframe animations.
  • Not easily reusable across multiple components without prop drilling.
  • Can make JSX verbose if styles are complex.
  • Harder to maintain consistency across the application.

import React from 'react';

function InlineStyledButton() {
    const buttonStyle = {
        backgroundColor: '#007bff',
        color: 'white',
        padding: '10px 20px',
        border: 'none',
        borderRadius: '5px',
        cursor: 'pointer',
        fontSize: '16px'
    };

    const handleClick = () => {
        alert('Button clicked!');
    };

    return (
        <button style={buttonStyle} onClick={handleClick}>
            Click Me (Inline Style)
        </button>
    );
}
    

Inline styles are suitable for small, isolated components or for dynamically applying styles based on very specific conditions. For broader styling, other methods are generally preferred.

CSS Modules: Encapsulated Styles

CSS Modules are a popular solution that aims to solve the problem of global CSS scope in component-based architectures. When you use CSS Modules, the CSS class names are automatically hashed and locally scoped to the component in which they are imported. This prevents class name collisions and makes your styles truly encapsulated and modular.

To use CSS Modules, you typically name your CSS files with the `.module.css` extension (e.g., `Button.module.css`). When you import this file into a React component, it becomes a JavaScript object where keys are your original class names and values are the unique, hashed class names.

Pros:

  • Guaranteed local scope: No more global class name conflicts.
  • Familiar CSS syntax: You write plain CSS.
  • Clear dependencies: Styles are explicitly imported.
  • Excellent for component-level styling.

Cons:

  • Can make global styling (e.g., typography, base resets) less straightforward.
  • Requires a build tool setup (Create React App handles this automatically).
/* Button.module.css */
.button {
    background-color: #28a745;
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
}

.button:hover {
    background-color: #218838;
}

.primary {
    font-weight: bold;
}

// In some cases, you might want to compose styles
// .composedButton {
//    composes: button;
//    border: 2px solid darkgreen;
// }
    
// Button.js
import React from 'react';
import styles from './Button.module.css'; // Import the CSS Module

function ModuleStyledButton() {
    return (
        <button className={`${styles.button} ${styles.primary}`} >
            Click Me (CSS Module)
        </button>
    );
}

// In the DOM, the class names might look like:
// <button class="Button_button__ab12c Button_primary__xy34z">...</button>
    

CSS Modules are a strong choice for ensuring style isolation in larger React applications and are widely adopted.

Styled Components (Brief Introduction): CSS-in-JS

Styled Components is a popular “CSS-in-JS” library. This approach allows you to write actual CSS code inside your JavaScript files, directly within your React components. Styled Components use tagged template literals (an ES6 feature) to define styles for your components, automatically generating unique class names for them.

Pros:

  • True component encapsulation: Styles are directly tied to the component and scoped.
  • Dynamic styling: Extremely powerful for styling based on props and state.
  • Theming support: Easy to implement complex theming.
  • No class name clashes.
  • Supports all CSS features (pseudo-selectors, media queries, keyframes).
  • Better developer experience for many, as CSS and component logic are in one place.

Cons:

  • Adds a small bundle size overhead.
  • Requires a new syntax/paradigm to learn.
  • Can lead to performance issues if not used carefully (e.g., recreating styled components on every render).

First, you’d install it: `npm install styled-components` or `yarn add styled-components`.

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

// Define a styled button component
const StyledButton = styled.button`
    background-color: ${props => (props.$primary ? '#007bff' : '#6c757d')};
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 16px;

    &:hover { /* Pseudo-class support */
        background-color: ${props => (props.$primary ? '#0056b3' : '#5a6268')};
    }

    @media (max-width: 768px) { /* Media query support */
        padding: 8px 15px;
        font-size: 14px;
    }
`;

function StyledComponentsExample() {
    return (
        <div>
            <StyledButton $primary>Primary Button</StyledButton>
            <StyledButton>Secondary Button</StyledButton>
        </div>
    );
}
    

Styled Components is highly popular in the React ecosystem for its power and flexibility in creating truly encapsulated and dynamic UI components.

CSS Frameworks (Brief Mention): Rapid UI Development

For rapid UI development and consistent design across a large application, many developers turn to CSS frameworks or component libraries. These frameworks provide pre-built, production-ready UI components and/or utility classes, allowing you to build interfaces much faster than writing all CSS from scratch. They often come with their own styling conventions and components.

Tailwind CSS

Tailwind CSS is a utility-first CSS framework. Instead of pre-built components, it provides a vast set of low-level utility classes that you can compose directly in your HTML (or JSX) to build custom designs. It focuses on enabling rapid development by reducing the need to write custom CSS. It’s often praised for its flexibility and the ability to easily customize every aspect of your design.

Example of Tailwind CSS classes in JSX:

<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
    Tailwind Button
</button>
    

Material-UI (MUI)

Material-UI (MUI) is a popular React component library that implements Google’s Material Design. It provides a comprehensive set of pre-designed and pre-built React components (like Buttons, Navbars, Cards, Forms) that adhere to Material Design guidelines. MUI aims to provide a fast way to build beautiful and accessible UIs. It abstracts away much of the underlying styling, letting you focus on component composition.

Example of using a Material-UI button component:

import Button from '@mui/material/Button';

function MaterialUIButtonExample() {
    return (
        <Button variant="contained" color="primary">
            Material-UI Button
        </Button>
    );
}
    

CSS frameworks and UI libraries like Tailwind CSS and Material-UI are excellent for accelerating development and maintaining design consistency, especially in larger projects or when you need a pre-defined design system. They can significantly reduce the amount of custom CSS you need to write and integrate seamlessly with React‘s component model.

References

You may also like