Neo Ighodaro Neo Ighodaro is a twenty-something-year-old full-stack web developer and graphic designer not based in Lagos, Nigeria.

The best “styling in React” tutorial you’ve ever seen

7 min read 2096

Styling In React Tutorial: You'll Get It Eventually

Alright, look. There’s no way for me to know how many “styling in React” tutorials you’ve seen, although I suspect not very many. If you haven’t seen any “styling in React” tutorials at all, you might be wondering, “Is this really the best one out there?”

Great question. Yes.

Is my editor taking liberties with this introduction? Also yes.

You’re here to learn about styling React components, and when you’re finished reading this post, you’ll know how to do just that.

What to expect

In this article, we are going to see various ways we can style React components. The methods of styling we will explore are:

  • Inline styling
  • styled-components
  • CSS Modules

We will be using a component that is part of a to-do application to explain each of these methods.

If you are new to React, you can check the official documentation to get started.

Setting up your React application

To set up an application, you can use create-react-app. It is the easiest way to get started with a React project. A CRA demo is out of the scope of the article, though, so we’ll skip that and style a make-believe to-do application.

Let’s get started with the first method.

Method #1: Inline styling of React components

If you are familiar with basic HTML, you’ll know that it is possible to add your CSS inline. This is similar in React.

We can add inline styles to any React component we want to render. These styles are written as attributes and are passed to the element. Let’s style parts of our component using inline styles:

class ToDoApp extends React.Component {
  // ...
  render() {
    return (
      <div style={{ backgroundColor: "#44014C", width: "300px", minHeight: "200px"}}>
        <h2 style={{ padding: "10px 20px", textAlign: "center", color: "white"}}>ToDo</h2>
        <div>
          <Input onChange={this.handleChange} />
          <p>{this.state.error}</p>
          <ToDoList value={this.state.display} />
        </div>
      </div>
    )
  }
}

So we just added inline styles to the outermost div and h2. Here are some things you should note about this.

First, there are two curly brackets. What we are rendering is written in JSX, and for pure JavaScript expressions to be used in JSX, they have to be included in curly brackets.

The first curly bracket injects JavaScript into JSX. The inner curly brackets creates an object literal. The styles are passed as object literals to the element.

💡 JSX is a preprocessor step that adds XML syntax to JavaScript. You can definitely use React without JSX, but JSX makes React a lot more elegant. Just like XML, JSX tags have a tag name, attributes, and children.

The next thing to note is that the properties are separated by a comma. This is so because what we are passing is an object. Since it is a JavaScript attribute, the attributes are written in camelCase and not separated by a dashes.

Now, in the code above, we just added a few properties to the elements we styled. However, imagine we had to add more and more styles to the element. This is where the inline method breaks down because it will not look clean.

There is a way around this, though. We can create object variables and pass them to the elements. Let us do that then.

Creating a style object variable

We create a style object variable the same way we create a JavaScript object. This object is then passed to the style attribute of the element we want to style.

So instead of adding the styles inline directly, as we did in the previous example, we just pass the object variables:

const TodoComponent = {
  width: "300px",
  margin: "30px auto",
  backgroundColor: "#44014C",
  minHeight: "200px",
  boxSizing: "border-box"
}

const Header = {
  padding: "10px 20px",
  textAlign: "center",
  color: "white",
  fontSize: "22px"
}

const ErrorMessage = {
  color: "white",
  fontSize: "13px"
}

class ToDoApp extends React.Component {
  // ...
  render() {
    return (
      <div style={TodoComponent}>
        <h2 style={Header}>ToDo</h2>
        <div>
          <Input onChange={this.handleChange} />
          <p style = {ErrorMessage}>{this.state.error}</p>
          <ToDoList value={this.state.display} />
        </div>
      </div>
    )
  }
}

In the code above, we created three object variables: TodoComponent, Header, and ErrorMessage. We are then passing these variables to the element instead of typing them directly.

💡 We did not have to use double curly brackets in the element because these variables are objects themselves.

If you look at the object properties, the camelCases will be converted to dash-separated CSS attributes during compilation. For instance, this:

backgroundColor: "#44014C",
minHeight: "200px",
boxSizing: "border-box"

In plain CSS, these will be written as:

background-color: #44014C;
min-height: 200px;
box-sizing: border-box;

⚠️ The camelCase to dash-separated string change applies only to the property names and not property values.

It is possible to pass a variable as a value to a property. So, we can do this:

const spacing = "10px 20px";
const Header = {
margin: spacing,
padding: spacing
// ...
}

In many JavaScript environments, creating a global object variable may be bad, but it’s fine in React. Since files are not visible to other files unless they are imported, we can create as many object variables even with the same name without having any conflict.

Sharing styles across many React components

The style objects and the components do not have to be in the same file. We can create a separate .js file for our styles, export these styles, and then import them into the component where we want to use them. Doing this makes styles reusable across multiple components. Let’s do this for our component.

First, we’ll create a separate .js file called styles.js. Then, add these styles:

const TodoComponent = {
  width: "300px",
  margin: "30px auto",
  backgroundColor: "#44014C",
  minHeight: "200px",
  boxSizing: "border-box"
}

const Header = {
  padding: "10px 20px",
  textAlign: "center",
  color: "white",
  fontSize: "22px"
}

const ErrorMessage = {
  color: "white",
  fontSize: "13px"
}

const styles = {
  TodoComponent: TodoComponent,
  Header: Header,
  ErrorMessage: ErrorMessage
}

In the code above, we can choose to export each style object individually, but that will mean importing them individually, too. That might get tedious if there are many style objects in the file.

Therefore, creating an object that contains all styles only makes sense. This object is exported and imported once to the component where it will be used. So let’s do that.

import React, { Component } from "react";

// Import the styles
import {styles} from "./styles";

class ToDoApp extends React.Component {
  // ...
  render() {
    return (
      <div style={styles.TodoComponent}>
        <h2 style={styles.Header}>ToDo</h2>
        <div>
          <Input onChange={this.handleChange} />
          <p style = {styles.ErrorMessage}>{this.state.error}</p>
          <ToDoList value={this.state.display} />
        </div>
      </div>
    )
  }
}

Line 4 is where we import the styles object. This object is then used to style components of our React app and is used just like any JavaScript object.

The thing to take home from this is that styles can be used and reused in multiple components. The styles just need to be imported and added to the style attribute.

That’s all for inline styling. Let’s move on to the next method.

Method #2: styled-components

With styled-components, we can write actual CSS in our JavaScript file. This means you can use all the features of CSS — like media queries, pseudo-selectors, nesting, etc. — in JavaScript.

styled-components uses ES6’s tagged template literals to style components. With it, the mapping between components and styles is removed. This means that when you’re defining your styles, you’re actually creating a normal React component that has your styles attached to it.

Using styled-components, we can create reusable components with styles. It is quite exciting to create and use. Explaining with an example here will do us a lot of good.

First, we need to install it, so run the following in your React app’s directory:

$ npm install --save styled-components

Let’s go back to our to-do app and make our component use styled components. First, we’ll import the styled-components package:

import styled from 'styled-components';

We can start using it right away. We’ll first create a styled component then see how we’ll use it:

const TodoComponent = styled.div`
background-color: #44014C;
width: 300px;
min-height: 200px;
margin: 30px auto;
box-sizing: border-box;
`;

Above we created a component that can be used the same as any React component. However, notice that we are using pure CSS in a JavaScript file. Next, let’s put this component to use:

class ToDoApp extends React.Component {
  // ...
  render() {
    return (
      <TodoComponent>
        <h2>ToDo</h2>
        <div>
          <Input onChange={this.handleChange} />
          <p>{this.state.error}</p>
          <ToDoList value={this.state.display} />
        </div>>
      </TodoComponent>
    )
  }
}

In the code above, we used the styled component we created — TodoComponent — on line 5 like we’ll use any other HTML element. The only difference is that it comes with its own predefined styles.

We can do the same for other parts of the component:

import styled from 'styled-components';

const TagComponent = styled.div`
  background-color: #44014C;
  width: 300px;
  min-height: 200px;
  margin: 30px auto;
  box-sizing: border-box;
`;

const Header = styled.h2`
  padding: 10px 20px;
  text-align: center;
  color: white;
  fontSize: 22px
`;

const ErrorMessage = styled.p`
  color: white;
  font-size: 13px;
`;

class ToDoApp extends React.Component {
  // ...
  render() {
    return (
      <TagComponent>
        <Header>ToDo</Header>
        <div>
          <Input onChange={this.handleChange} />
          <ErrorMessage>{this.state.error}</ErrorMessage>
          <ToDoList value={this.state.display} />
        </div>
      </TagComponent>
    )
  }
}

To find out more about styled components and how to use them, you can read the official documentation here.

Now let’s discuss the third and final way to style in React.

Method #3: CSS Modules

A CSS Module is a CSS file in which all class names and animation names are scoped locally by default. Take note of the words scoped locally. Let’s break that down a little bit.

CSS class names and animation names are scoped globally by default. This can lead to conflict, especially in large stylesheets; one style can override another. This is the problem CSS Modules solves. CSS classes are only available within the component where they are used.

A CSS module is basically a .css file that is compiled. When compiled, it produces two outputs. One is CSS that is a modified version of input CSS with the renamed class names. The other is a JavaScript object that maps the original CSS name with the renamed name.

Let’s see an example of how this works. However, if you want to dig deeper, check out this article on it. Alright, let’s create a CSS class in a module for a sample error message. The name of our module is styles.css:

.error-message {
color: red;
font-size: 16px;
}

When compiled, this will produce something like this:

.error-message_jhys {
color: red;
font-size: 16px;
}

The added jhys is just a sample key (which I added myself) that is used to uniquely identify this class. As said earlier, it produces a JS object, which can be imported in the React file and used:

{
    error-message: error-message_jhys
}

Let’s see how we can use this now:

import styles from './styles.css';
class Message extends React.Component {
     // ... 
    render() {
        return (
I am an error message
) } }

Remember that the main purpose of CSS Modules is to make CSS classes locally scoped and avoid conflicts in naming.

Conclusion

So, there we have it — three ways to style a React component. Generally, all the methods are useful, and depending on the project’s size, you can use whichever.

Hope you learned a thing or two about styling in React. If you have any questions or feedback, please leave a comment below.


Plug: LogRocket, a DVR for web apps

LogRocket Dashboard Free Trial Banner

LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.

Neo Ighodaro Neo Ighodaro is a twenty-something-year-old full-stack web developer and graphic designer not based in Lagos, Nigeria.

Leave a Reply