Styling Components in React

Published | 4 min read

As I mentioned in my previous posts there are quite a few ways to create components in React.js. As it happens there are also quite a few ways to style components as well.

The great thing about React is you can create components in isolation. However, if you are not careful you could end up with conflicting CSS styles.

CSS has come a long way especially with the ability to use Sass and Less to create computed styles but you still need to be careful to make sure you aren’t affecting something else in your application. For anyone who has had to use !important you know what I am talking about.

So let’s have a look at the different ways to style components.

Adding standard classes

There are a few cases where you are going to need to use standard css classes. As we saw in my previous post, class is a protected keyword in JSX. To deal with this we have to use className instead.

function PrimaryButton({ children }) {
  return <button className="button is-primary">{children}</button>
}

The attribute className works in exactly the same was as class does in normal HTML and you can use it to reference styles from an external style sheet.

This is particularly useful if you are converting an existing project to use React or you are referencing class names from an external package. You can import stylesheets directly into your components with import ./Button.css.

Inline CSS

Another way of styling React components is with inline CSS. This is probably my least favourite way of styling components in react but it does solve the issue of having conflicting styles as the styles are scoped to the component.

The style that you provide to the component is written as a javascript object and uses camel case instead of the normal css casing. e.g. border-colour becomes borderColor.

const buttonStyle = {
  backgroundColor: '#00d1b2',
  borderColor: 'transparent',
  color: '#fff',
  cursor: 'pointer',
  justifyContent: 'center',
  paddingBottom: '.5em',
  paddingLeft: '1em',
  paddingRight: '1em',
  paddingTop: '.5em',
  textAlign: 'center',
  whiteSpace: 'nowrap',
}

function PrimaryButton({ children }) {
  return <button style={buttonStyle}>{children}</button>
}

It is easy to get caught out if you forget to camel case when of your styles with this method.

CSS Modules

Another way to scope styles to the component is to use CSS modules. With CSS modules you can write your styles in a standard style sheet.

button.css

.button {
  cursor: pointer;
  justify-content: center;
  padding-bottom: 0.5em;
  padding-left: 1em;
  padding-right: 1em;
  padding-top: 0.5em;
  text-align: center;
  white-space: nowrap;
}

.primary {
  background-color: #00d1b2;
  border-color: transparent;
  color: #fff;
}

button.jsx

import styles from './button.css'

function PrimaryButton({ children }) {
  return (
    <button className={[styles.button, styles.primary].join(' ')}>
      {children}
    </button>
  )
}

When you are using multiple classes that are imported in this way you can’t just reference them in the string as they are variables. One option is to use the join method shown in the example above.

Another option is to use template literals:

import styles from './button.css'

function PrimaryButton({children}) {
  return <button className=`${styles.button} ${styles.primary}`>{children}</button>
}

You can also use the classnames package which is a bit more natural to write.

import styles from './button.css'
import classnames from 'classnames'

function PrimaryButton({ children }) {
  return (
    <button className={classnames(styles.button, styles.primary)}>
      {children}
    </button>
  )
}

One of the great things with classnames is you can also do conditional classes. This is particularly useful if you want to programmatically have styles apply.

import styles from './button.css'
import classnames from 'classnames';

function PrimaryButton({children}) {
  return <button className={classnames(styles.button,{styles.primary : true})}>{children}</button>
}

Styled Components

The last method I am going to share today is using the styled-components library. Styled components allow you to add css styles that are locally scoped without the need to create separate css files.

import styled from 'styled-components'

const Button = styled.button`
  cursor: pointer;
  justify-content: center;
  padding-bottom: 0.5em;
  padding-left: 1em;
  padding-right: 1em;
  padding-top: 0.5em;
  text-align: center;
  white-space: nowrap;

  background-color: ${props => props.primary && '#00d1b2'};
  border-color: ${props => props.primary && 'transparent'};
  color: ${props => props.primary && '#fff'};
`

<Button primary>Click Me</Button>

You can also create styled components from other components.

import styled from 'styled-components'

const Button = styled.button`
  cursor: pointer;
  justify-content: center;
  padding-bottom: 0.5em;
  padding-left: 1em;
  padding-right: 1em;
  padding-top: 0.5em;
  text-align: center;
  white-space: nowrap;
`

const PrimaryButton = styled(Button)`
  background-color: #00d1b2;
  border-color: transparent
  color: #fff
`

<PrimaryButton>Click Me</PrimaryButton>

Final thoughts

There are many ways to style components in React. Which one you use will depend on the project you are working on. If you are using an external stylesheet from a library such as Bootstrap or Bulma then simple CSS classes is probably best.

Of course if you have additional styling you want to use on top you could always use styled-components as well.


Was this post useful?
If you found this post useful and would like to support me, you can do so by buying me a coffee. Donations help keep this blog ad free.

ALSO ON ALEXHYETT.COM

What is DeFi? Understanding Decentralized Finance

What is DeFi? Understanding Decentralized Finance

  • 19 November 2021
If you are new to the crypto space the concepts of decentralised finance can seem a bit overwhelming. There are so many new terms to try and understand, it can be challenging to see how everything fits together. I have been working in the traditional...
Using Hashnode as a Source for Gatsby

Using Hashnode as a Source for Gatsby

  • 05 November 2021
I have done quite a few website migrations over the years. My blog like many first started out on WordPress. After several attempts at optimisation, I ended up generating a static version of my WordPress website. On my static site generation journey...
What is Web3? The Decentralised Internet Explained

What is Web3? The Decentralised Internet Explained

  • 15 October 2021
If you have stumbled upon this article you have probably seen the term web3 being mentioned around the internet. Especially on Twitter at the moment it seems to be the latest buzzword. With all the hype around NFTs and crypto at the moment, a lot of ...
Ditch the Ads: The Future of Website Monetization

Ditch the Ads: The Future of Website Monetization

  • 08 October 2021
Do you remember that scene in Ready Player One, when IOI are showing what the future of the Oasis will look like once they take over? “We have determined that we’ll be able to fill 80% of the user’s display with advertising before inducing seizures”...
Dealing with Imposter Syndrome as a Software Developer

Dealing with Imposter Syndrome as a Software Developer

  • 28 May 2021
I have been a professional software developer for over a decade and I have been writing code for over 25 years. However, sometimes I still feel like a fraud. It turns out, I am not the only one that feels this way and they have a name for it, it is c...
Mocking API calls using WireMock

Mocking API calls using WireMock

  • 14 May 2021
It is rare in software development that you are building something in complete isolation from everything else. Generally, you are going to be making calls to other systems or components. If you are lucky you are building against an existing API that ...
Using ngrok to test local websites and APIs

Using ngrok to test local websites and APIs

  • 07 April 2021
Often when I am creating a new website, I want to see how it is going to look on an actual device like my phone or tablet. You can use Chrome Web Tools for mimicking a device but it isn’t the same as an actual phone. Chances are however that if you t...
Using GitHub Actions to Deploy to S3

Using GitHub Actions to Deploy to S3

  • 26 March 2021
Recently I went through the process of setting up Drone CI on my Raspberry Pi. The plan was to use my Raspberry Pi as a build server for this website as well as other projects. However, the Sharp image library that Gatsby uses to resize images doesn’...

Alex Hyett
WRITTEN BY

Alex Hyett

Software Developer, Entrepreneur, Father, and Husband. Engineering Lead at Checkout.com.

Want to get in touch? You can find me here:


Join the Newsletter

Subscribe to get my latest content by email.

    I won't send you spam. Unsubscribe at any time.