React

Everything you need to know about Styled Components

Paul CcariPaul Ccari
May 04, 2021 β€’ 9 min read

Photo by Rafael Guajardo on Pexels

When I started learning CSS, it seems pretty straightforward to play with some selectors and apply styles to any elements but as bigger, as my projects get, my style sheets look more chaotic and you've probably experienced it for yourself. At some point, it gets hard to figure out a good way to organize your styles.

Then you probably jump to use some preprocessors like SASS, LESS which add a lot of useful features but they don't do much to control CSS specificity unless you start using some methodologies like BEM (Block, Element, Modifier) which allows reuse of existing code without duplications and divide UI into independent blocks.

After a couple of years, a new paradigm of CSS-in-JS appears and tries to solve these problems to construct and manage our styles in a component-specific manner to allows us to create custom, exportable components.

One of them is Styled Components, it provides us many cool features to style our React components.

  • It generates unique class names for your styles which means that you won't have any issues with duplication, overlap, or misspellings.
  • You can adapt styles of a component based on its props which makes dynamic styling.
  • Easier to maintain styles no matter how big is your application while still writing CSS you know

Styled components are available both for React and React Native

Installation

You can install it running a single command and you're ready to roll:

npm install --save styled-components

Getting Started

Style an HTML element

We are going to create a Title component based in an HTML element like h1 to give some styles like giving a purple color and align it to center to use is it in Blog Page.

import styled from 'styled-components';
import * as React from 'react';

const Title = styled.h1`
  color: purple;
  text-align: center;
`;

const BlogPage = () => {
  return (
    <div>
      <Title> Personal Blog </Title>
      ...
    </div>
  );
};

export default BlogPage;

Style a React Component

What if we already have a set of custom React components and we want to extend styles? It's almost similar, when you want to style an HTML element, you put a dot. If you want to style the components, you put parentheses and pass the actual component. In this case, we are gonna style a button from material-ui and adjust his size with css.

import Button from '@material-ui/core/Button';

const FullWidthButton = styled(Button)`
  width: 300px;
`;

Keep in mind that you can style pseudo-selectors and classes inside of the styled component if needed.

const Button = styled.button`
	...

	:hover {
		color: blue;
	}

	::before {
		content: ' ';
		...
	}
`;

Note: Styled components works with Tagged template literal under the hood. If you don't know much about it, you can find more info here FreeCodeCamp.

Creating Global Styles

To give global style, we need to use createGlobalStyle and create a constant from it and anything inside of here will be styled in our entire application. This will be a component that needs to be called at the Root component and make sure it starts with an uppercase.

import { createGlobalStyle } from 'styled-component';

const GlobalStyles = createGlobalStyle`
	body {
		font-family: Roboto;
	}
`;

export default function App() {
  return (
    <>
      <GlobalStyles />
      ...
    </>
  );
}

Adjust Style based on props

We can set dynamic styles according to props that can be either true or false based on conditionals.

A simple case would be to give some styles to stand out recent blog posts we published from all the list. I'm gonna give a gradient color to the background of card.

const BlogCard = styled(Card)`
	...
	${props =>
			props.isNewPost &&
			`
				background: linear-gradient(to right, red, orange);
			`
		}
`

export default function BlogList(){
	return(
		<>
			<BlogCard
				isNewPost
				title="Everything you need to know about Styled Components"
				...
			/>
			<BlogCard
				title="Learning Tips from my experience as developer"
				...
			/>
		</>
	)
}

Style a component based on complex props

In some scenarios, we will have a prop that can be a string and not only a boolean value which means we will have more conditionals.

Intro to Styled Components & React

Eg. I have a list of blog post cards and I would love to change the color of its category according to its value. If it's personal we'll set it to purple color, if it's react should be orange and if it's git let's change it to red.

const CategoryName = styled.span`
  font-size: 0.875rem;
  color: ${({ topic }) => {
    if (topic === 'personal') return 'purple';
    if (topic === 'react') return 'blue';
    if (topic === 'git') return 'red';
    return 'black';
  }};
`;

export default function BlogCard() {
  return (
    <Card>
      ...
      <CategoryName category={category}>{category}</CategoryName>
      ...
    </Card>
  );
}
Intro to Styled Components & React

Animations

To create animations in styled components, we need to import keyframes and start writing our css animation code. Then we need to reuse that variable where we needed.

In this case, we'll animate the position of an h1 to go from left to right.

import { keyframes } from 'styled-components';

const move = keyframes`
	from {
		transform: translateX(0);
	}
	to {
		transform: translateX(100%)
	}
`;

const Heading = styled.h1`
  animation: ${move} 2s ease infinite;
`;

Create and use a Theme

To ingrate a theme on our application, we need to use the ThemeProvider and pass an object to it's theme prop. We will use this theme to set colors and fonts.

import { ThemeProvider } from 'styled-components';

// create Theme object
const theme = {
  colors: {
    purple: '#123123',
    blue: '#2563eb'
  },
  fonts: {
    heading: 'Roboto, sans-serif',
    body: 'Montserrat'
  }
};

// how to use it in a styled component
const Heading = styled.h1`
	text-align: center;
	color: ${(props) => props.theme.colors.purple}
	font-family: ${({ theme }) => theme.fonts.body} // destructuring props
`;

// Call ThemeProvider in your Root Component
export default function App() {
  return (
    <ThemeProvider theme={theme}>
      <Heading>Hello its from the theme</Heading>
    </ThemeProvider>
  );
}

Using css prop to define styles

Sometimes we don't want to create an extra component to just apply a bit of styling and there it comes css prop. It works on HTML tags as well as components and supports everything styled components support including props, theme and custom components.

To enable support for the css prop you have to use a babel plugin or macro.

Usage with the babel plugin

// Babel plugin does that automatically!

// HTML element
<div
  css={`
    background: papayawhip;
    color: ${props => props.theme.colors.text};
  `}
/>

// Custom component
<Title
  css="padding: 0.5em 1em;"
/>

Usage with Babel macro

// You need to import it manually
import styled from 'styled-components/macro';

// Custom component
<div
  css={`
    background: papayawhip;
    color: ${(props) => props.theme.colors.text};
  `}
/>;

Note that Babel plugin or macro turns any elements with a css prop into a styled components.

Using as prop to reassign the HTML tag

In some instances, we want to keep all styling we've applied to a component but just change what element/component is being rendered.

I usually use it when it comes about anchor tags and buttons. We don't need to rewrite the css rules and create a component for our anchor tag when it has the same look and feel with our buttons. Instead, we can use as and then pass the attributes the anchor needs.

const Button = styled.button`
	...
`

<Button as="a" href="https://www.google.com.pe"> Go to Google.com </Button>

Using attrs method to add HTML attributes

It allows us to change and add attributes to our styled elements. The attrs object accepts either any type of attribute that belongs to HTML tags or a function that receives props to finally merged them into existing component props.


// In this case, type `button` is going to override whatever is in component
const Button = styled.button.attrs({
	type: "button"
})`
	display: inline-block;
	...
`

// We can use props
const Button = styled.button.attrs(props => ({
	type: props.type || "button"
}))`
	display: inline-block;
	...
`

<Button type="submit">Submit</Button>

Use Styled Components with the Object Syntax

There is also another way that we can style components, we can use object-based styling. Let's see how different that is. At the end, both ways do exactly the same thing and they are just different ways of writing styled components

const Title = styled.h1((props) => ({
  color: red,
  fontSize: props.small ? 16 : 24, // by default its pixel
  fontFamily: 'sans-serif'
}));

Final Notes

As you can see, it's actually pretty easy to understand and start using styled-components in your React applications. There are some features that can help us to custom our component the way we want, make some dynamic styling using props, creating a theme and so on. So I would encourage you to dive into the documentation and try it out on your projects.

Here are a few miscellaneous link related that help me to understand more about styled components

Hope you enjoyed it. Thanks for reading!

... As always, enjoy your own process of learning πŸš€

Feel free to reach out if you wanna chat about anything.

Site designed & coded by Paul Ccari using React + TypeScript + TailwindCSS + MDX + Nextjs.

Lets Talk!

I am always open to collaborate, build cool stuff, or help with coding challenges. Feel free to drop an β€œHi or Hola” back, or just writing me a tweet, or sending me an email.

Plus, you can follow me onFrontendUIwhere I keep creating content about front-end stuff.

@ Paul Ccari, 2021. All Rights Reserved.

Portfolio made with inPeru.