Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 40

React Styling Approaches

Recommended resources

Hello! Welcome to the first lesson in our module on styling. In the previous modules, you've become proficient at building the structure and logic of React components using props, state, and effects. Now, it's time to make them look great.

This lesson addresses a fundamental question every React developer faces: "What is the best way to style my application?" As you'll soon see, there isn't one single answer. Instead, there's a spectrum of approaches, each with its own philosophy, benefits, and drawbacks.

Our goal today is to compare the most popular styling strategies in the React ecosystem. We'll explore:

  • Traditional global CSS and its limitations.
  • CSS Modules for locally scoped styles.
  • CSS-in-JS libraries like Styled Components.
  • Utility-First CSS frameworks like Tailwind CSS.

By the end of this lesson, you will be able to compare these different approaches and understand the trade-offs involved, enabling you to make informed decisions for your future projects.

5 Ways to Style a React Application
There are many ways to style a React app. We'll focus on the most modern and widely used methods.

1. The Starting Point: Global CSS

The most straightforward way to style a web application is to use a plain CSS file. This is how web development has worked for decades. In a React project set up with Vite, you can import a CSS file directly into your main App.jsx or main.jsx file, and the styles will be applied globally.

Let's watch a quick demonstration of this method and hear about its primary challenges in a component-based architecture.

How to Style your React App (5 Different Methods Compared)

The video 'How to Style your React App' by Eric Murphy starts by explaining the traditional CSS approach and why it often falls short in modern React development.

Watch from 00:24 to 01:38. Pay close attention to the problems mentioned, such as class name conflicts and maintaining a large, single stylesheet.

As the video highlights, the main problem with global CSS is the global scope. In a large application built with hundreds of components, it becomes nearly impossible to manage class names without them colliding. You might change a style for one component, only to find you've unintentionally broken the layout of another. This leads to fragile styles and a fear of refactoring.

To solve this, developers created new approaches that embrace React's component-based nature.


2. Solution 1: Locally Scoped Styles with CSS Modules

What if we could write standard CSS, but ensure that the styles for one component could never accidentally affect another? That's the core idea behind CSS Modules.

A CSS Module is a regular CSS file, but with a special naming convention: [ComponentName].module.css. When you import this file into your component, the build process (handled by Vite) automatically transforms your class names into unique, locally-scoped identifiers.

How to Style your React App (5 Different Methods Compared)

Let's continue with the same video to see how CSS Modules solve the global scope problem.

Watch from 01:38 to 04:24. Notice how the class name is imported as an object property (styles.primary) and how it's rendered as a unique string in the browser's developer tools.

How it works:

  1. You create a file like Button.module.css with a class .primary.
  2. In your Button.jsx component, you import it: import styles from './Button.module.css';
  3. You apply the class using object notation: <button className={styles.primary}>.
  4. Vite transforms styles.primary into something unique like Button_primary__a24kF, preventing any clashes.

CSS Modules are a great step forward because they offer style isolation while letting you write familiar CSS.


3. Solution 2: Component-Driven Styles with CSS-in-JS

The next major evolution in React styling was the CSS-in-JS movement. The philosophy is simple: if our component's structure (JSX) and logic (JavaScript) are already in the same file, why not put the styles there too?

Libraries like Styled Components and Emotion are the most popular implementations of this idea. With these libraries, you define your styles using JavaScript template literals and they generate actual React components with those styles attached.

This approach allows for powerful, dynamic styling based on your component's props.

7 ways to deal with CSS

The Fireship channel provides a fast-paced overview of CSS-in-JS. This will give you a quick sense of the core concept and its benefits.

Watch from 02:41 to 03:40. Focus on how styles can be written directly inside the component file and how they can change dynamically based on the application's state or props.

Key Advantages of CSS-in-JS:

  • Co-location: Styles live right next to the component logic, making components truly self-contained.
  • Dynamic Styling: It's trivial to change styles based on props (e.g., <Button primary>).
  • No Class Names: You think in terms of components (<PrimaryButton>) rather than class names.

However, this power comes with a trade-off: runtime performance. Because the styles are defined in JavaScript, the browser must execute that JS to generate and inject the CSS, which can add overhead compared to static CSS files.


4. Solution 3: The Utility-First Approach with Tailwind CSS

A more recent and extremely popular approach is Utility-First CSS, with Tailwind CSS as its leading framework.

The philosophy here is radically different. Instead of writing custom CSS for your components, you style elements by applying a large set of pre-existing, single-purpose utility classes directly in your JSX.

For example, instead of writing a CSS class card with display: flex; box-shadow: ...;, you would write:
<div className="flex shadow-lg ...">

This might seem messy at first, but it has profound benefits for speed and consistency.

How to Style your React App (5 Different Methods Compared)

Let's see Tailwind CSS in action. This clip from Eric Murphy's video introduces the basic idea.

Watch from 07:31 to 09:00. Observe how complex styling is achieved just by combining small, descriptive class names in the className attribute.

Key Advantages of Utility-First:

  • Rapid Development: You rarely need to leave your HTML/JSX to write new CSS rules.
  • Design Constraints: Everyone on the team uses the same spacing, color, and typography scale, leading to more consistent UIs.
  • Performance: Tailwind automatically removes all unused utility classes from your final CSS file, resulting in an extremely small bundle size.
  • No Naming Things: You don't have to spend mental energy coming up with good class names like .user-profile-card-header.

5. A Head-to-Head Comparison

We've now seen three major modern styling paradigms. Let's dig deeper into their trade-offs with a more detailed article.

Styling in React: CSS Modules vs Styled Components vs Tailwind

The article 'Styling in React: CSS Modules vs Styled Components vs Tailwind' from TeachMeIDEA offers an excellent breakdown of these three approaches, focusing on practical considerations like performance and team workflow.

Please read the following sections: 'CSS Modules', 'Styled Components', 'Tailwind CSS', and 'Performance Comparison'. As you read, think about how each approach handles styling differently and the performance implications of those choices.

Let's summarize the key differences in a table based on what you've just read and watched.

Criterion CSS Modules Styled Components (CSS-in-JS) Tailwind CSS (Utility-First)
Paradigm Scoped, file-based CSS Component-based JS styles Composing utility classes
Performance Excellent. Zero runtime cost. Styles are compiled to static CSS. Good. Some runtime overhead from JS evaluating and injecting styles. Excellent. Zero runtime cost. Generates a static, highly optimized CSS file.
Developer Experience Write standard CSS in .module.css files. Write CSS inside JavaScript template literals. Compose utility classes directly in JSX. Excellent IDE support.
Dynamic Styling More complex. Requires passing different class names or using inline styles. Excellent. Natively supports changing styles via props. Good. Apply classes conditionally in JSX based on state/props.
Bundle Size Good. Only the CSS for rendered components is included. Fair. Requires a runtime library, adding to the JS bundle. Excellent. Purges all unused styles, resulting in a tiny CSS file.

When to Use Each Approach

So, which one should you choose? The best choice depends heavily on your project's needs and your team's preferences.

Styling in React: CSS Modules vs Styled Components vs Tailwind

The same article provides a fantastic summary that can help you decide. Let's read its final recommendations.

Read the section 'When to Use Each Approach'. This will give you a clear, concise guide for choosing a styling solution.

To summarize the article's advice:

  • Choose CSS Modules if: You and your team love writing traditional CSS but want to avoid the pitfalls of global scope. It's safe, predictable, and has no performance overhead.
  • Choose Styled Components if: You are building a component library or a design system, or if your UI requires highly dynamic styles that frequently change based on application state.
  • Choose Tailwind CSS if: You want to build and iterate on UIs extremely quickly, value consistency, and want the best possible performance without sacrificing developer experience.

For the remainder of this course, we will be using Tailwind CSS. Its rising popularity, excellent performance characteristics, and focus on rapid development make it a fantastic choice for modern React projects.


Conclusion

Congratulations on navigating the complex landscape of React styling! You now have a solid framework for understanding the pros and cons of the most popular methods.

Key Takeaways:

  • Global CSS is simple but doesn't scale well in component-based apps due to a lack of scope.
  • CSS Modules solve the scope problem by making styles local by default, but you still write traditional CSS in separate files.
  • CSS-in-JS (e.g., Styled Components) co-locates styles with components and excels at dynamic styling, but at the cost of some runtime overhead.
  • Utility-First CSS (e.g., Tailwind CSS) enables rapid development with pre-defined classes and produces highly optimized, performant stylesheets.
  • The best choice depends on your project's specific needs, and for this course, we will proceed with Tailwind CSS.

Next Up:

Now that we've compared the options and made our choice, it's time to get our hands dirty. In the next lesson, we will walk through the process of setting up and configuring Tailwind CSS in your Vite React project, so you can start building beautifully styled components.