August 09, 2020
This is a quick start guide to learning Styled Components, the component-driven CSS methodology used in React.
If you want to start practicing and applying Styled Components to your projects, this guide will help you get started.
Ready? Let’s dive in:
Styled Components is a library for React & React Native to write and manage your CSS.
It’s a “CSS-in-JS” solution, meaning you write your CSS in Javascript files (specifically within your components, which are Javascript files).
It’s an extremely popular solution for managing CSS in React, with around 8 million npm downloads/month and 30k stars in Github.
A familiarity and understanding of React is recommended before diving into Styled Components.
A few benefits of the styled-components library are:
To get started with styled-components, you first need to install it into your project:
npm install styled-components
And on every file that you use styled-components, you’ll need to add this import:
import styled from 'styled-components';
And that’s it! You’re ready to start working with styled-components.
Open up an existing React project you’re working on (or quickly whip up a new project with create-react-app), and open up one of your existing components.
Here, you can add your first Styled Component.
Now that you have styled
imported, here’s how you get started:
// App.jsimport React from 'react';import styled from 'styled-components';// Button component that'll render an <a> tag with some stylesconst Button = styled.a`background-colour: teal;color: white;padding: 1rem 2rem;`const App = () => {return (<Button>I am a button</Button>)}export default App;
Let’s break this code down:
const Button
styled
is what we imported above, and gives us the Styled Components functionalitya
after styled
? This represents the anchor HTML element: <a>
. When declaring a Styled Component, you can use any HTML element here (e.g. <div>
, <h1>
, <section>
etc.)Make sense?
The <Button>
returned inside the App component looks like a normal React component. And that’s because it is a React component!
In our previous example, we created a Styled Component inside an existing component.
But you can also create a Styled Component in its own file.
For example, create a new component file called Button.js, and add a Styled Component:
// Button.jsimport styled from 'styled-components';const Button = styled.a`background-colour: teal;color: white;padding: 1rem 2rem;`export default Button;
Button
now works like any other React component. For example, we can now import this component into other components files:
// App.jsimport React from 'react';import styled from 'styled-components';// import the styled component:import Button from './Button';const App = () => {return (<Container><Button>I am a button</Button></Container>)}export default App;
And there you have it!
Congratulations, you just built your first Styled Component!
Imagine you have a <Button />
component, and you need to style different variants of that button (primary, secondary, danger, etc).
Styled Components have an elegant solution for this, where you leverage props to make your component styles dynamic.
Let’s dive right into an example to show you what I mean.
Here we are rendering two Button components, one with a primary
prop:
// App.jsimport React from 'react';import styled from 'styled-components';import Button from './Button';const App = () => {return (<><Button>I am a button</Button><Button primary>I am a primary button</Button></>)}export default App;
And now, inside our <Button />
component, we can add the dynamic styles:
// Button.jsimport styled from 'styled-components';const Button = styled.a`display: inline-block;border-radius: 3px;padding: 0.5rem 0;margin: 0.5rem 1rem;width: 11rem;border: 2px solid white;background: ${props => props.primary ? 'white' : 'palevioletred' }color: ${props => props.primary ? 'palevioletred' : 'white' }`export default Button;
What’s happening here is you’re interpolating a function that is returning a CSS value (using a ternary operator) based on the props.
That was quite a mouthful.
To put it more simply, background: ${props => props.primary ? 'white' : 'palevioletred' }
essentially means:
If the prop primary
is true, then the background should be white
, else the background should be palevioletred
.
Handling props like this works in some use-cases, but it can get messy if you have multiple props (e.g. primary, secondary, danger, etc.) as well as multiple lines of CSS.
Often, it makes more sense to import { css }
from styled-components
like this:
// Button.jsimport styled, { css } from 'styled-components';const Button = styled.a`display: inline-block;border-radius: 3px;padding: 0.5rem 0;margin: 0.5rem 1rem;width: 11rem;background: transparent;color: white;border: 2px solid white;${props => props.primary && css`background: white;color: palevioletred;`}`export default Button;
This keeps your dynamic styles separate for different props.
For example, adding styles for a danger
prop would look like this:
// Button.jsimport styled, { css } from 'styled-components';const Button = styled.a`display: inline-block;border-radius: 3px;padding: 0.5rem 0;margin: 0.5rem 1rem;width: 11rem;background: transparent;color: white;border: 2px solid white;${props => props.primary && css`background: white;color: palevioletred;`}${props => props.danger && css`background: red;color: white;`}`export default Button;
Nice! We’re making some good progress.
How about making this <Button />
a little more responsive, eh?
Thankfully, making your Styled Components responsive is super simple.
Add media queries inside your template literal, like this:
// Button.jsimport styled from 'styled-components';const Button = styled.a`display: inline-block;border-radius: 3px;padding: 0.5rem 0;margin: 0.5rem 1rem;width: 9rem;background: transparent;color: white;border: 2px solid white;@media (min-width: 768px) {padding: 1rem 2rem;width: 11rem;}@media (min-width: 1024px) {padding: 1.5rem 2.5rem;width: 13rem;}`export default Button;
If you’re looking for a more involved example with multiple different device sizes, I recommend checking out this Javascript Ramblings article.
Similarly to adding media queries to your Styled Components, adding pseudo selectors is pretty straightforward.
For example, adding a hover state to our <Button />
component would look like this:
// Button.jsimport styled from 'styled-components';const Button = styled.a`display: inline-block;border-radius: 3px;padding: 0.5rem 0;margin: 0.5rem 1rem;width: 9rem;background: transparent;color: white;border: 2px solid white;:hover {border-color: green;}`export default Button;
One of the main mental models of React is how you treat everything as components.
You essentially break an interface down into tiny chunks and piece it all together in a scalable way.
This approach comes with many advantages, but does however surface a challenge:
How to style parts of your design that are consistent across multiple components?
Or put another way:
How can you set global styles?
For example, you might want to:
Styled Components has a solution for global styles using the createGlobalStyle
function.
First, navigate to the component which is at the top of your React tree.
For example, if you’re working in a create-react-app project, that’ll be your App.js
file.
Here, you’ll need to import createGlobalStyle
into your project, and set some styles to a GlobalStyle
component (you can name this component how you like):
// App.jsimport React from 'react';import styled, { createGlobalStyle } from 'styled-components';import { Container, Nav, Content } from '../components';const GlobalStyle = createGlobalStyle`body {margin: 0;padding: 0;background: teal;font-family: Open-Sans, Helvetica, Sans-Serif;}`;const App = () => {return (<Container><Nav /><Content /></Container>)}export default App;
This isn’t going to apply the styles to the project yet.
Now we need to use the GlobalStyle
component to apply the global styles to the application.
You do this by placing the GlobalStyle
component at the top of your React tree:
// App.jsimport React from 'react';import styled, { createGlobalStyle } from 'styled-components';import { Container, Nav, Content } from '../components';const GlobalStyle = createGlobalStyle`body {margin: 0;padding: 0;background: teal;font-family: Open-Sans, Helvetica, Sans-Serif;}`;const App = () => {return (<><GlobalStyle /><Container><Nav /><Content /></Container></>)}export default App;
Notice the use of fragments short syntax?
This is required as you’re placing the <GlobalStyle />
component as a sibling at the top of the tree.
And that’s it!
Global styling is now all set up with Styled Components.
Nice job if you’ve made it all the way to the end.
We covered a lot! Specifically:
Those are the fundamentals to get you off and running with Styled Components.
Like learning anything new, practicing is key. Give Styled Components a shot in your next project and see where it takes you!
Levelling up your React and CSS skills in 2021 is a great idea. Here's why: