This is a multi-part series of articles where I am going to show you how we can leverage the power of styled-components and styled-system to create reusable, efficient components. We are in components age of Frontend. We can relate a component to lego. Similar to legos we can have small reusable components that can be attached to build bigger components which can be further combined with other components to create amazing things. Let’s start with styled-components at first.
Add the styled-components package to your project.
yarn add styled-components
styled-components utilizes tagged template literals to style your components. To get a better understanding Let’s create a simple Text Component.
import styled from 'styled-components';
const Text = styled.p`
color: orange;
font-size: 20px;
font-weight: bold;
letter-spacing: 0.5px;
`;
In the above example, we are extending the existing p tag from HTML DOM. And giving it more styles. For those of you who don’t know what () means herein styled components. It’s called template literal. Whenever you extend a tag or a component by styled components it returns a React Component. This React Component is exactly like normal components and behaves same. To understand more let’s try to create a button component.
const Button = styled.button`
background: orange;
color: white;
font-size: 15px;
padding: 10px 30px;
border: none;
border-radius: 3px;
font-weight: 500;
margin: 20px;
`;
const App = () => props => <Button>Hello World</Button>
From this you can imagine how easy it is to create a reusable component with styled-components. However, there seems to be one problem. React components are customizable their behavior can be controlled by passing props to them. How good is a styled-component if it cannot be easily customizable. In the next phase, we will learn how to make this component accept and behave according to the props.
ACCEPTING PROPS:
Before making a component able to accept props, it’s important to figure out the key styles that define a component. In case of a button those styles can be background and text color (possibly outline, solid states if you want something advanced).
Styled-components allows us access to the prop values component receives. With this, we can modify the key styles based on props. Let’s try to modify the button component so that we can respond to the props and create different variants of a button.
const Button = styled.button`
background: ${props => (props.bg ? props.bg : "orange")}
color: white;
font-size: 15px;
padding: 10px 30px;
border: none;
border-radius: 3px;
font-weight: 500;
margin: 20px;
`;
const App = () => (
<div>
<Button bg="#FF595E">Danger Button</Button>
<Button>Default Button</Button>
</div>
);
We are now not hardcoding the background of the button component instead we have passed a function which checks if a prop called bg exists. if it exists we are going to use it as a background else we are going to go with a default orange. Now we have a button component that accepts a bg (background) prop. We can create a lot of components similarly. If you want to optimize the function we wrote for the background you can simply write this:
background: ${props => props.bg};
The only problem with this syntax is that you always need to pass bg prop whenever you use this component else the background won’t be set. One of the easiest ways to fix this to use default props.
Button.defaultProps = { bg: 'orange' };
This always provides a default bg prop to the component so we don’t have to worry about passing a bg prop each time we use this component. This example seems pretty basics. But in real life projects, some components are very complex. I will show you an example of a component that allows us to modify a lot of key style elements.
import React from "react";
import styled from "styled-components";
const CardWrapper = styled.div`
background: ${props => props.bg};
width: 350px;
margin: auto;
padding-bottom: 20px;
border-radius: ${props => props.borderRadius}px;
`;
const Image = styled.img`
width: 100%;
height: auto;
border-radius: ${props =>
`${props.borderRadius}px ${props.borderRadius}px 0 0`};
`;
const Title = styled.h3`
color: ${props => props.titleColor}
margin: 0;
padding: 15px;
`;
const Description = styled.p`
color: ${props => props.textColor};
padding: 0px 15px;
margin: 0;
`;
const Card = ({
image,
title,
description,
titleColor,
textColor,
borderRadius,
...props
}) => (
<CardWrapper borderRadius={borderRadius} {...props}>
<Image src={image} borderRadius={borderRadius} alt={title} />
<Title titleColor={titleColor}>{title}</Title>
<Description textColor={textColor}>{description}</Description>
</CardWrapper>
);
Card.defaultProps = {
bg: "white",
titleColor: "#1982c4",
textColor: "#999",
borderRadius: 5
};
const App = () => (
<Card
image="assets/react-image.png"
title="Card Title"
description="Lorem ipsum dolor sit amet, consectetur adipiscing"
/>
);
This is just an example to show how we can use multiple styled components to create bigger reusable components. We can add a lot of additional features to this component to make it more customizable. In the next part, I will share you how we can eliminate writing all those mini functions inside styled-components and create a reusable component in a better, faster and efficient way. Part 2
Top comments (2)
Can you please elaborate about best practice for using styled-components?
Styled components itself is very clear, but just few things you need to consider are: