Styled Components in React and TypeScript

Michael Gold
7 min readAug 30, 2022

--

Introduction

This article will run through an example of using the styled-components feature in React in order to style your React components with css. The prerequisite for this article is having nodejs installed. You can install it here. You can use any IDE you want to follow this article, but my tool of choice is Visual Studio Code for all React and TypeScript work.

Once node is installed, let’s begin installing React with TypeScript. Run the following node script from the command line in a folder:

npx create-react-app my-app --template typescript

Running the line above will produce a sample react project in TypeScript that we can use to code up our example.

Template React TypeScript App produced by npx generator

We are going to start by editing App.tsx(the main app component) to be a simple button that when pressed changes the background color of an small area in the browser.

Here is the code to replace in App.tsx that does just that:

import React, { useState } from 'react'
import logo from './logo.svg'
import './App.css'
const App = () => {
const colors: string[] = ['red', 'brown', 'lightgreen', 'yellow', 'green', 'orange', 'purple', 'blue' ]
const [areaColor, setAreaColor] = useState('white') const changeToRandomColor = () => {
setAreaColor(colors[Math.floor(Math.random() * colors.length)])
}
return (
<>
<div style={{ width: '50px', height: '50px', background: areaColor }}>{areaColor}</div>
<button onClick={changeToRandomColor}>change color</button>
</>
)
}
export default App;

The div in the render part of the App component has embedded styling. It is styled as a square with a width of 50px and a height of 50px. The div’s background color is assigned a value according to the state called areaColor.

The button has no styling, but when the button is clicked in calls changeToRandomColor which will update the div’s state randomly to one of the colors in the colors array.

When we run the code using:

npm run start

We get the following application running on localhost:3000 on our browser. Note if you press the button, it will show a square with the name and backgroud of a random color:

Button Causes Random Color to Display when Clicked

Clicking the button will display a different random color chosen from the colors array and use it as the background color inside the square.

Introducing Styled Components

In our sample application, we styled the div with an embedded style. Let’s start by moving this style over to a styled component and maybe also sprucing it up a bit. First we’ll remove the embedded style from our div except for the areaColor. We’ll leave that for now:

<div style={{ background: areaColor }}>{areaColor}</div>

Now let’s install styled-components so we can do the styling using them. At the command line in the same directory as package.json, run the following command:’

npm install --save styled-components

You will know if it installed properly by seeing that styled-components shows up in your package.json file as a dependency:

"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.2",
"@types/node": "^16.11.56",
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"styled-components": "^5.3.5",
"typescript": "^4.8.2",
"web-vitals": "^2.1.4"
}

Now let’s create our first styled component for the div we had previously styled and call it StyledColorBlock. We’ll create this component in a file called index.tsx.style as a sibling file of index.tsx. In it, we’ll create our styled component as follows:

import styled from 'styled-components'export const StyledColorBlock = styled.div`
width: 50px;
height: 50px;
`

Note with a styled component, we simply assign our component to a base html component, and style the component with css.

Now all we need to do is use our styled component in our App.tsx file in place of the existing div. Don’t forget to import the styled component at the top of App.tsx! :

import { StyledColorBlock } from './index.style'const App = () => {
const colors: string[] = ['red', 'brown', 'lightgreen', 'yellow', 'green', 'orange', 'purple', 'blue' ]
const [areaColor, setAreaColor] = useState('white') const changeToRandomColor = () => {
setAreaColor(colors[Math.floor(Math.random() * colors.length)])
}
return (
<>
<StyledColorBlock style={{background: areaColor }}>{areaColor}</StyledColorBlock>
<button onClick={changeToRandomColor}>change color</button>
</>
)
}
StyledColorBlock used in place of div

Let’s take it a step further. Instead of a square let’s make our div a circle by rounding the corners, and let’s put a nice black border around the circle. Let’s also put a little margin around the circle to give it some space from the button and finally let’s center the text using flex:

import styled from 'styled-components'export const StyledColorBlock = styled.div`
width: 100px;
height: 100px;
border-radius: 50px;
outline: solid 3px black;
margin: 20px;
display: flex;
justify-content: center;
align-items: center;
`

Now our StyledColorBlock and button looks something like this in the browser:

Square Becomes a Circle with Centered Text

Adding parameters to a styled component

Let’s say we want to eliminate any style attribute information from App.tsx and move it to the StyledColorBlock. In that case, we would need to pass in the areaColor into the StyledColorBlock instead of embedding it in the style. So how do we go about doing that? Well, you can actually pass parameters directly to the styled component itself. Let’s see how this is done:

Let’s start by replacing the style attribute on StyledColorBlock with a new attribute called fill and passing in the areaColor state to our styled component.

<StyledColorBlock fill={areaColor}>{areaColor}</StyledColorBlock>

We can receive our fill prop into the background of the StyleColorBlock as shown below.

export const StyledColorBlock = styled.div < { fill: string } >`
width: 100px;
height: 100px;
border-radius: 50px;
outline: solid 3px black;
margin: 20px;
display: flex;
justify-content: center;
align-items: center;
background: ${prop => prop.fill}
`

This syntax is unique to style components, and the background property is actually receiving a function that returns the prop’s fill value.

If we go run npm:

npm run start

we see the same exact result we did with the embedded style:

Removing the embedded style and replacing with a prop to the Styled Component

Handling Events

Let’s spruce up our button a little bit by making the button a styled component. We’ll add a new styled component into our index.style.tsx file called StyledChangeColorButton. This styled component uses the component style.button.

export const StyledChangeColorButton = styled.button `
width: 100px;
height: 32px;
background: #CC0055;
outline: solid 2px purple;
margin: 30px;
color: white;
border-radius: 5px
`

We’ll replace our existing button in App.tsx with this new styled component button.

Changing the generic button appearance with Styled Components

Now let’s say we want to change this button’s color to blue every time we hover over it. Styled components let us handle typical browser states with the ability to add them to the style component’s css. Below we added the hover event handler into our button styled component to cause the background color change to blue:

export const StyledChangeColorButton = styled.button `
width: 100px;
height: 32px;
background: #CC0055;
outline: solid 2px purple;
margin: 30px;
color: white;
border-radius: 5px;
&:hover {
background: blue;
}
`

And the result displays in the browser when we hover over the button as shown:

Changing the Button Appearance when we Hover Over it

Animating the Circle

Let’s see if we can spin our circle around in real time and have it grow as it spins.

We need to import the styled components keyframes library in order to accomplish this. Then we’ll use the keyframes to animate our circle div. To use the keyframes component for rotation and scaling we’ll rotate the circle div from 0 to 360 degrees. Then we’ll specify at each keyframe percentage what our circle size and font size is to make the circle look like it’s growing and rotating at the same time.

export const pulseAnimation = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
0% { font-size: 5px; width: 25px; height: 25px; }
33% { font-size: 10px; width: 40px; height: 40px; }
66% { font-size: 15px; width: 75px; height: 75px; }
100% { font-size: 20px; height: 100px; width: 100px; }`
Animating the circle by spinning it and growing it at the same time

Conclusion

Styled components are a powerful addition to react and provide a great way to organize the css styling of your React components so your React does not get cluttered. In this article we learned to use style components to enhance the appearance of our components, how to pass react props to the styled component, how to respond to events on the styled component and finally how to animate the styled component. We hope you enjoyed reading.

If you want to learn more about React, you can purchase my book Creating Wordle using React and TypeScript.

--

--