Styled Components 101 ๐Ÿ’… Lecture 1: Introduction + Setup in a React Environment โš›๏ธ

Styled Components 101 ๐Ÿ’… Lecture 1: Introduction + Setup in a React Environment โš›๏ธ

ยท

7 min read

Hello, everybody! ๐Ÿ‘‹

And welcome to the first lecture of the Styled Components 101 series.

In this series, we will be thoroughly covering different topics related with Styled Components.

Still don't know what Styled Components are? It seems like you're in luck because we start with the first lesson right now! ๐Ÿ‘‡

What are Styled Components? ๐Ÿ’…

Styled Components is a modern tool used to generate components out of the most basic HTML elements, which also allows you to write your custom CSS styles for them in JavaScript by making use of the tagged template literals feature.

Styled Components gets rid of the mapping between components and styles, so, when declaring your CSS, what you're actually doing is creating a regular React component that has its own styles attached.

Installation ๐Ÿ–ฅ

If you use npm:

npm install styled-components

If you use yarn:

yarn add styled-components

Getting Styled Components ready to work with React โš›๏ธ

This is the best part: no extra configuration is needed to start using Styled Components with React. In next lectures, we'll see how to configure Styled Components to get it to work with frameworks like Next.js and how to integrate them with SSR (Server Side Rendering). But, for now, everything's ready on React side. Keep tuned to this series of Styled Components if you want to learn further ๐Ÿ˜บ

Creating our first styled component ๐Ÿฃ

There are a couple ways to define a styled component. Personally, my favorite is to keep the component independent, defined in its own file, as we regularly do with React components. But, although conceptually speaking, this is the best way of keeping an app properly modularized and making good use of abstraction, the approach of declaring a styled component within another component is widely extended as well. Not my favorite, but also valid.

Our first styled component will be a Button. Let's see how we can define it using the Styled Components syntax:

StyledButton.js

import styled from "styled-components";

export default styled.button`
   background-color: #7b4cd8;
   color: #fff;
   padding: 10px;
   border: none;
   border-radius: 5px;
   font-size: 1.25rem;
`

As you can see in the example above, we're using plain CSS syntax inside of backticks (``) to make our styles understandable to JavaScript.

And then, we just have to import our component wherever we want it to be rendered:

import StyledButton from "./components/StyledButton";

const MyApp = () => {
   ...
   return(
      <StyledButton>I am a styled button! ๐Ÿ˜ผ</StyledButton>
   )
   ...
}

export default MyApp;

Our first styled button will look like this:

b1.png

Styling our component through props ๐Ÿ’โ€โ™‚๏ธ

In the previous example, all the styles have been predefined by us and every rendered StyledButton will have the exact same appearance.

But, can we render the same type of component multiple times to create different components and apply different styles to them? The answer is yes and what we're going to do to get this behavior is passing props with custom values to our styled button.

Let's say we want to have three buttons with different background and text colors, but with the same padding, border radius and font size.

Then, we're going to do something like this:

StyledButtonWithProps.js

import styled from "styled-components";

export default styled.button`
   background-color: ${props => props.bg};
   color: ${props => props.color};
   padding: 10px;
   border: none;
   border-radius: 5px;
   font-size: 1.25rem;
`

Let's now call our three buttons:

import StyledButtonWithProps from "./components/StyledButtonWithProps";

const MyApp = () => {
   ...
   return(
      <StyledButtonWithProps bg="#ffc3c3" color="#b6201e">Button ๐Ÿ“</StyledButtonWithProps>
      <StyledButtonWithProps bg="#ffdaca" color="#d85d16">Button ๐Ÿ‘</StyledButtonWithProps>
      <StyledButtonWithProps bg="#fff4c7" color="#bb9922">Button ๐Ÿ‹</StyledButtonWithProps>
   )
   ...
}

export default MyApp;

And this is the result:

b2.png

Styling our component conditionally ๐Ÿ’

Let's now have a look at how we can style our button component by adding some conditions.

This time, let's say we want to have a different background color for our button depending on its type value, which will be passed in to the component through the prop buttonType.

Then we should do the following:

StyledButton.js

import styled from "styled-components";

export default styled.button`
   ${props => props.buttonType && props.buttonType === "primary" ?
   `background-color: #7b4cd8; color: #fff; font-size: 1.25rem;` :
   `background-color: #ff31ca; color: #ffe6f9; font-size: 0.95rem;`
   };
   padding: 10px;
   border: none;
   border-radius: 5px;
`

If the prop buttonType exists and has a value of primary, then the component will get the first set of style properties. Otherwise, the second.

Note that the style properties defined outside the condition block, remain the same for all components.

Let's now call our buttons:

import StyledButton from "./components/StyledButton";

const MyApp = () => {
   ...
   return(
      <StyledButton buttonType="primary">I am a Primary Button! ๐Ÿ‘†</StyledButton>
      <StyledButton>I am a different kind of button! ๐Ÿ‘‡</StyledButton>
   )
   ...
}

export default MyApp;

And there we are:

b3__.png

Inheriting styles from another component ๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ

Even though the aforementioned method of passing style properties by using component props works well in every scenario, if our app starts to grow, we can find the process of creating components tedious and repetitive.

And now's when constructors come to rescue: we can have a supercomponent (like a superclass, making reference to inheritance in OOP ๐Ÿค“), whose styles can be inherited by other components.

This means that every children component that inherits from the supercomponent will have the supercomponent styles in addition to its own custom styles.

Let's see how we can connect them:

SuperButton.js

import styled from "styled-components";

export default styled.button`
   color: #fff;
   width: 200px;
   height: 50px;
   border: none;
   border-radius: 5px;
   font-size: 1.25rem;
`

ChildrenButton.js

import styled from "styled-components";
import SuperButton from "./SuperButton";

export default styled(SuperButton)`
   background-color: ${props => props.bg};
`

Let's now call them all:

import ChildrenButton from "./components/ChildrenButton";

const MyApp = () => {
   ...
   return(
      <ChildrenButton bg="deeppink">Hello! ๐Ÿ‘‹ </ChildrenButton>
      <ChildrenButton bg="hotpink">Hello! ๐Ÿ‘‹ </ChildrenButton>
      <ChildrenButton bg="coral">Hello! ๐Ÿ‘‹ </ChildrenButton>
   )
   ...
}

export default MyApp;

And this is the result:

b4.png

Can I use CSS preprocessors like SASS or LESS to write my styles instead of plain CSS?

Not really. But you can still make use of their most common features.

Styled Components is based on the paradigm CSS-in-JS, so, technically, we need to use plain CSS to define them. However, we can kinda emulate the behavior of a preprocessor: Styled Components allows us to define variables and nest selectors, for example.

The following snippet would be far correct in Styled Components:

StyledDiv.js

import styled from "styled-components";

export default styled.div`
   p{
      font-family: 'Arial', sans-serif;
      font-size: 1.5rem;
      color: deeppink;
      &.primary{
         font-weight: bold;
      }
   }
`

Now we call it:

import StyledDiv from "./components/StyledDiv";

const MyApp = () => {
   ...
   return(
      <StyledDiv>
         <p className="primary">Hello from a Styled Div!</p>
      </StyledDiv>
   )
   ...
}

export default MyApp;

And this is what we get:

b5.png

This behavior is doable because Styled Components uses a preprocessor, called stylis, under the hood, so it supports scss-like syntax, which is really cool for nesting and using pseudo-elements and pseudo-classes out of the box.

So, that means I can also add a nested pseudo-element to my styled component, right? ๐Ÿค”

Absolutely yes.

This time, we're going to define a <p> element to append some content to it. Let's take a step further and let's add that content based on a condition.

StyledP.js

import styled from "styled-components";

export default styled.p`
   {$props => props.before ? `
   color: #7b4cd8;
   &::before {
      content: "${props.before}";
   }
` : 
   `color: #ff31ca;`
   }
`
import StyledP from "./components/StyledP";

const MyApp = () => {
   ...
   return(
      <StyledP before="_">CODE</StyledP>
      <StyledP>I don't have a ::before ๐Ÿ˜ข</StyledP>
   )
   ...
}

export default MyApp;

Et voilร :

b6.png

If a prop called before is found, its value will be appended in front of the <p> element and the component will receive the specified text color. Otherwise, since the condition would never be satisfied, the only style property the component would get would be the color.


And this is all for this first Styled Components 101 lecture!

In next episodes, we'll keep delving into all the amazing features of Styled Components and how we can integrate them into our projects.

I hope you found this article useful and I see you all in the next ๐Ÿ‘‹


๐ŸŽ‰ Don't forget to follow @underscorecode on Instagram and Twitter for more daily webdev content ๐Ÿ–ฅ๐Ÿ–ค


ย