Everything you need to know about Styled Components
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.
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>
);
}
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
- Build your own styled-components library
- A quick introduction to Tagged Template Literals
- Enabling support for the css prop in 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.