CSS and React Components

Learn about styled-components, the library that helps us include CSS and React code together.

Introduction

Where Stimulus encourages using the markup we are already writing, therefore keeping CSS in its own separate files, React encourages thinking about CSS and code together. Once we get in the habit of thinking of our page as made up of a number of different React components, it’s a small step to imagine those components containing their own CSS for features that are specific to that component.

Including CSS with React code is so common that there are many libraries that can handle this. We’re going to talk about one of these libraries that has an interesting way to insert CSS into our React code: the styled-components library.

Introducing styled-components

The styled-components library allows us to define React components that include CSS styles inside the definition of the component. When the component renders, the styled-components library generates CSS code with definitions for these styles and uses those generated CSS class names in the rendered HTML markup. In practice, this means that we’re not attaching CSS definitions to the big components we’ve already defined. Rather, we’re attaching them to the internal markup of the components that use div, and span is replaced with styled-components that define their own CSS.

CSS with React Components

Why would we do this if CSS seems good enough? CSS is great, but there are a few reasons why it’s helpful to bundle CSS with React components:

It’s easier to see what CSS applies to a component because the styling is right there in the same file as the component. There tends to be a better separation of styling from logic and, as a result, the logic components tend to be a little cleaner. The library gives us some protection against style bugs, such as using the wrong CSS class. It also prevents unused CSS from being sent to the page. The styled-components library has strong support for global properties. There are also a few challenges associated with bundling CSS with React components:

  • It’s easier to see what CSS applies to a component because the styling is right there in the same file as the component.
  • There tends to be a better separation of styling from logic and, as a result, the logic components tend to be a little cleaner.
  • The library gives us some protection against style bugs, such as using the wrong CSS class. It also prevents unused CSS from being sent to the page.
  • The styled-components library has strong support for global properties.

There are also a few challenges associated with bundling CSS with React components:

  • Syntax is problematic, especially for dynamic properties and especially with TypeScript. We’ll probably want an editor plugin to help.
  • It can be difficult to debug the resulting CSS without additional plugins.
  • It can encourage an overreliance on divs that make the layout harder to manage long term.

Overall, though, styled-components are interesting and worth considering in our project. Let’s add some.

Installing styled-components

With TypeScript, we have to install two packages, and we’re going to install an optional third package that will give us slightly better tooling in development:

yarn add styled-components
yarn add @types/styled-components
yarn add babel-plugin-styled-components --dev

We need to add the Babel plugin to the plugins section of the babel part of our package.json. My babel section now looks like this:

"babel": {
  "presets": [
    [
      "./node_modules/@rails/webpacker/package/babel/preset.js"
    ],
    [
      "@babel/preset-typescript"
    ]
  ],
  "plugins": [
    "babel-plugin-styled-components"
  ]
},

Now we can use the styled-components library on the components that we added with React.

Our First Styled Component

Let’s look at our React components and see how we can use the styled-components library. As a reminder from Managing State in React, we currently have four components with display elements on our concert view page: a VenueHeader that adds a header, a VenueBody that controls the grid, a Row that manages a row of seats, and a Seat that draws an individual seat.

Our first styled-components change is in VenueHeader. We want to change the styling of the text prompt and manage the spacing a bit. Otherwise, the functionality is the same: when the option changes, we pass the new value back to the same ticketsToBuyChanged handler, stored in the Venue component and passed to VenueHeader via a prop.

Right at the top of the file we import styled-components. Then the real action comes with our declaration of Header:

Get hands-on with 1200+ tech skills courses.