Tutorial

How To Use Emotion for Styling in React

React

Introduction

React allows you to style components directly with the style property. For most situations, using the style prop to pass an object of CSS properties is sufficient.

However, for situations that require more demanding styling features, emotion can provide a solution. emotion is a flexible and highly performant CSS-in-JS library. It accepts strings and objects, supports defaulting and extending variables, and with an additional Babel plugin even supports inline child selectors.

In this article, you will build a React application that uses the @emotion/react and @emotion/styled packages for styling.

Prerequisites

To complete this tutorial, you’ll need:

Note: This article previously recommended the emotion and react-emotion packages. Now several versions later, @emotion/react and @emotion/styled are the modern approach.

This tutorial was verified with Node v15.3.0, npm v7.4.0, react v17.0.1, @emotion/react v11.1.4, and @emotion/styled v11.0.0.

Step 1 — Setting Up the Project

Start with using create-react-app to generate a React App and then install dependecies:

  • npx create-react-app react-emotion-example

Change into the new project directory:

  • cd react-emotion-example

Next, install @emotion/react and @emotion/styled via npm:

  • npm install @emotion-react@11.1.4 @emotion/styled@11.0.0

At this point, you will have a new React project with @emotion/react.

Step 2 — Using the css Prop

emotion provides a css prop that can accept nested selectors and media queries. It can support an object or a tagged template literal.

Open the App.js file in your code editor and modify it to use <div>s with the css prop:

src/App.js
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';

function App() {
  return (
    <div>
      <div css={css({
        margin: 10,
        padding: 10,
        backgroundColor: '#eee',
      })}>
        This is an example of <code>`css`</code> using an object.
      </div>
      <div css={css`
        margin: 10px;
        padding: 10px;
        background-color: #eee;
      `}>
        This is an example of <code>`css`</code> using a tagged template literal.
      </div>
    </div>
  );
}

export default App;

The first example uses an object with style object properties and values. The second example uses a tagged template literal with CSS rules.

Note: Since this tutorial is relying upon Create React App 4, it is necessary to specify /** @jsxImportSource @emotion/react */. This comment informs Babel to customize the automatic runtime import.

Run the application:

  • npm start

Observe the application in your browser. This will produce two identical <div>s with ten pixels of margin, ten pixels of padding, and grey background color.

Step 3 — Using the styled Components

emotion also supports a styled component to create an element and style it. It can also support an object or a tagged template literal.

Let’s consider a Heading component that generates a h1 heading element and accepts bg (background) and fg (foreground) properties that will set the background-color and color:

const Heading = styled('h1')`
  background-color: ${props => props.bg};
  color: ${props => props.fg};
`;

When using this Heading component, you will be able to pass color values to bg and fg:

<Heading bg="#008f68" fg="#fae042">
  Heading with a green background and yellow text.
</Heading>

Revisit App.js in your code editor and modify it to use styled components:

src/App.js
import styled from '@emotion/styled';

const Heading = styled('h1')`
  background-color: ${props => props.bg};
  color: ${props => props.fg};
`;

function App() {
  return (
    <div>
      <Heading bg="#008f68" fg="#fae042">
        Heading with a green background and yellow text.
      </Heading>
    </div>
  );
}

export default App;

This code will result in an h1 element with a green background and yellow text.

Next, consider a Subheading component that extends the Heading component and changes the rendered text using withComponent:

const Subheading = Heading.withComponent('h2');

Instead of a h1 heading, the component will render with a h2 heading.

This code will produce an h2 with default colors:

<Subheading>
  Subheading with default colors.
</Subheading>

This code will produce an h2 with light green text:

<Subheading fg="#6db65b">
  Subheading with light green text.
</Subheading>

This code will produce an h2 with a light green background:

<Subheading bg="#6db65b">
  Subheading with light green background.
</Subheading>

You can specify your styles as an object instead of as a string:

const Quote = styled('blockquote')(props => ({
  fontSize: props.size,
}));

And even include an object of default styles:

const Cite = styled('cite')(
  {
    fontWeight: 100
  },
  props => ({
    fontWeight: props.weight
  })
);

That can be optionally set when using the component.

This code uses the default fontWeight value:

<Cite>
  Citation with light text!
</Cite>

This code provides a weight prop which overrides the default fontWeight value:

<Cite weight={700}>
  Citation with heavy text!
</Cite>

With emotion you can specify !important styles:

const Footer = styled('footer')`
  margin-top: 50px !important;
`;

This code produces a footer element with a margin-top of 50 pixels.

Step 4 — Using css Props and styled Components

Now, reflect on what you have learned in the previous examples and use those concepts to construct a component that uses css props and styled components.

Revisit App.js with your code editor and replace the content with
the following lines of code:

src/App.js
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
import styled from '@emotion/styled';

const Heading = styled('h1')`
  background-color: ${props => props.bg};
  color: ${props => props.fg};
`;

const Subheading = Heading.withComponent('h2');

const Quote = styled('blockquote')(props => ({
  fontSize: props.size
}));

const Cite = styled('cite')(
  {
    fontWeight: 100
  },
  props => ({
    fontWeight: props.weight
  })
);

const Footer = styled('footer')`
  border-top: 1px solid #ccc;
  color: #ccc;
  margin-top: 50px !important;
  padding-top: 20px;
`;

function App() {
  return (
    <div css={css`background: #ddd;`}>
      <div css={css({ padding: 10 })}>
        <Heading bg="#008f68" fg="#fae042">
          Quotations
        </Heading>
        <Subheading fg="#6db65b">
          For React Developers
        </Subheading>
        <Quote size={28}>
          I built this with <code>`emotion/react`</code> and <code>`emotion/styled`</code>!
        </Quote>
        <Cite weight={700}>Sammy</Cite>
        <Footer>Shark Facts</Footer>
      </div>
    </div>
  );
}

export default App;

This code utilizes css props and styled components with strings and objects. It also utilizes extending styled components using withComponent and overriding styled components with default values.

Conclusion

In this article, you built a React application that uses the @emotion/react and @emotion/styled packages for styling.

If you’d like to learn more about React, take a look at our How To Code in React.js series, or check out our React topic page for exercises and programming projects.

Creative Commons License