Deep dive into styled components & theming the App

Learn how to add styled-components to your application

We’re going to style the basic create react app with styled-components to look something like this:


But first, preamble✨: I have always struggled with styling sites, it seems to be an aspect of starting web development that is either an afterthought or glossed over. Up until December last year I didn’t really like styling anything at all with CSS, it was a chore rather than something I enjoyed doing.

There’s some basic CSS concepts in this post that I was not aware of before starting out with styled-components that I presume are assumed in styling web pages.

Styling the body element of a site is assumed, so for when you are starting out with a blank canvas there are some defaults for all modern web browsers you add to your site, like leaving font size at 16px (or 1rem) or box-sizing: border-box; there’s some packages out there to take care of this for you as well.

. . .

Versions:

This guide is being used with the following dependency versions.

react: 16.2.0 react-dom: 16.2.0 react-scripts: 1.1.0 styled-components: 3.1.6

Install styled-components

Ok lets bootstrap the basic react application you get when using Create React App with npx, if you already have Create React App installed globally then you can use the command without npx.
npx create-react-app style-with-styled-components cd style-with-styled-components/ npm i styled-components

Ok, now we have the basic app we can style, thankfully Dan has kindly provided the starting styles for us so let’s begin my using them with styled-components.
The way the CRA CSS is laid out, assumes that you will have a corresponding CSS file for each component, which can help with maintaining the CSS and lends to the React idea of having all your files separated into their component parts.

We can start with the App.js file and it’s accompanying App.css file. Let’s take a look at the App.js first:


In styled-components we’d create components for each of these elements that replace the aforementioned className’s. Ok we can start by migrating our styles into components, let’s do one component first to get an idea of where we’re going with this.

First, import styled into the App.js module:
import styled from 'styled-components'

Now lets look at <div className="App">, it’s the top level div for this component and is what I like to call the wrapper for the component. So lets give it an imaginative name AppWrapper.

Referring to the App.css there is text-align: center; which belongs to this, so:
const AppWrapper = styled.div` text-align: center;`

So here we have defined the AppWrapper const as a styled.div followed by back ticks `` inside of the back ticks we can write any regular CSS with the exact same CSS syntax you wold in a normal .css file.

Now that we have our AppWrapper we can replace the top level div on the App.js component.


styled-components all the things

So let’s do that for the remaining four CSS classes, and take a look, I’ll define them underneath the AppWrapper here:


So first off we’ve created a variable for the React svg animation, you’ll need to import the keyframes helper from styled-components like so:
import styled, { keyframes } from 'styled-components'

this can now be used throughout the App.js component and we can add an on hover selector to any of our styled-components within this module. Here we’re going to add it to the AppLogo to keep the super sweet rotating React logo.
const AppLogo = styled.img` animation: ${rotate360} infinite 120s linear; height: 80px; &:hover { animation: ${rotate360} infinite 1.5s linear; } `

Ok, our app shouldn’t look any different as we haven’t added in our styled-components to the app render() method, so let’s do that now.

Let’s also change the intro text. You can add a wrapper for the <code> tags something like:
const CodeWrapper = styled.code` font-size: 1.3rem; `

But if you prefer you can nest selectors within the component, like:
const AppIntro = styled.p` color: ${props => props.theme.dark}; font-size: large; code { font-size: 1.3rem; } `

Let’s have a look at the render() method now…


Now all the classes originally used in App.js have been replaced so there’s no need for the import './App.css' mapping, remove that aaaaand! Still no change!! Which is a good thing because at the moment we’re swapping out the .css files for styled-components.

Cool, we have now replaced all the css with styled-components, now we can take a look at injectGlobal.

Lets take a look at how the App.js file should look before we move on:


. . .


Theming

Themes are often used to change the look and feel of a wide range of things at once. For example, you may have a night and day mode like in Twitter. You can create your own themes in styled-components too.
Twitter with day and night theme
Twitter with day and night theme


Use the styled-components ThemeProvider

Now say we want to have several components in our app that use a CSS colour property color: #6e27c5 instead of hard coding it through the app for every component that uses it we can use the styled-components ThemeProvider.

For this we will need to import the ThemeProvider named export from styled-components, then define a theme object where our colour is going to live:
export const theme = { primary: ‘#6e27c5’ }

Let’s add the newly created theme to the globalStyle module we created previously.

To make the theme object available throughout the app component we’ll wrap our app component in the ThemeProvider and import our awesome theme for use in the ThemeProvider:

Now the theme properties can be used as props in our styled-components, let’s change the background-color: in the AppHeader component, whilst we’re at it let’s add a dark: #222 property to our theme object and use that for the color property:
const AppHeader = styled.div` height: 12rem; padding: 1rem; color: ${props => props.theme.dark}; background-color: ${props => props.theme.primary}; `

Now we can change our app theme globally


Ok cool, can you change theme?

This is what I was thinking and it turns out you can, there’s a great Stack Overflow answer from Max on it.

It got me thinking if you can switch between themes rather than define them for different sections like in the SO answer.

I started off by defining two themes (with imaginative names) in the globalStyle.js module:


Now we need a way to switch between the two theme objects, let’s use a select box for them, let’s create a components folder and in there make a ThemeSelect.js component, we can worry about refactoring the
App.jscomponent when I’m not here :

ThemeSelect.js

You’ve probably noticed the onChange={e => this.props.handleThemeChange(e) event, we’re going to add that method to the App.js component along with some state to manage what theme is selected.

App.js


To summarise what we have done with App.js here is, add some state to default to theme1 where the two themes are imported as named exports of the globalStyle.js module.

Add a method to handle the change of the ThemeSelect.js component handleThemeChange this is where we can switch between the two themeobjects.

Let’s try it out, we should be able to switch between the two themes we’ve defined now.


. . .


Want to know more?

A great resource for getting started with styled-components which really helped me is Simon Vrachliotisegghead.io styled-components playlist which is a great foundation for starting out with styled-components 👌 the first lesson is for pro members but the rest are currently available to watch fro free.

There’s also the spectrum.chat community and of course Stack Overflow.
Chris Gregori

May 8 2019

Write your response...

On a mission to build Next-Gen Community Platform for Developers