React Styled Components before V4

Abdelfattah Atef
tajawal
Published in
8 min readOct 14, 2018

Before talking about styled-components I need to mention a quote for every Frontend developer who doesn’t like style elements and believes that its so easy but CSS is not as EASY as you thought!

When you code CSS, you are writing abstract rules to take unknown content and organize it in an unknown medium. THAT SHIT IS HARD — keith K Grant

Copyright from Google Images

In the early stages, we needed a way to style our websites, so supposedly CSS was responsible for styling our websites.

But after a while, we needed to create dynamic sites. so CSS became a mess because every developer started the CSS in his/her way and there is no consistent pattern to write CSS and this caused a big issue because of their effect on the specificity of the elements and the developers had to override styles using !important to display the UI Element as they need

but we realized that:

DON’T USE !IMPORTANT

and these issues increase when the project grows in size, complexity, and team members.

Here are an attempts to fix these issues!

Preprocessors Appearing

Preprocessors like Sass and less are an extension of CSS that adds power and elegance to the basic language. It allows you to use variables, mixins, conditions, nesting and extends.

And we could separate CSS code to multiple files but after compilation, this CSS code will be in one global bundled file so the same issue of the overriding will still occur.

Naming Conventions Appearing

After that, Naming conventions like BEM ( Block, Element, Modifier) has appeared and it’s a CSS methodology to write CSS, so that all classes will be unique and if you need to know more about BEM you can check out my article about BEM Methodology, thus we decreased the risk of the specificity and overriding the elements styles

But there are lots of issues appeared:

  • The class name is very long.
  • It’s difficult to select a class name.

Now let’s talk about css-in-js role in General

CSS-in-JS has lots of benefits to use it like:

  • Create unique class names to avoid the repetition of naming the class.
  • Avoid specificity conflicts.
  • No need to worry about how the order of files is imported.
  • Linters show unused components so they can be removed if not used because we are writing JS.
  • Add vendor prefixes only for the required browser.

and now there are a lot of CSS-in-JS libraries like styled-components, glamorous, emotion, radium, and styled-jss.

Now let’s talk about styled components and it’s one of the popular libraries of css-in-js.

The styled component is created by Max Stoiber to remove the mapping between components and styles.

This means that when you’re defining your styles, you’re actually creating a normal React component, that has your attached styles.

Before installing a styled component let’s install first react application then install styled components

npx create-react-app react-styled-component

For more info regarding installing your react app you can check out this link create react app

After finishing installing you should use this command to start your app

npm start

then your browser will be opened to this tab

After Running Our React App

Now you can install styled component using this command

npm install --save styled-components

Then make sure the “styled-components” plugin is added to your .babelrc.

{
"presets": ["env", "react"],
"plugins": ["styled-components"]
}

After that we will try to convert our App.js component to styled component

and App.js file will looks like:

Hence let’s include styled from styled-components

import styled from 'styled-components';

Accordingly, let’s create the wrapper for this component and use it directly instead of <div className=”App”>

then remove all styles related to this class .App from app.css

Now let’s create Header component instead of using header tag in HTML5

then remove all styles related to this class .App-header from app.css

Now let’s create HeaderImage component instead of using imgtag

then remove all styles related to this class .App-logo from app.css

Now let’s create Bio and HeaderLinkcomponents instead of using p and a tags

and remove all styles related to .App-link this class from app.css

Now your components should look like itself as before.

but now we need to import keyframes from styled-component to remove animations styles from app.css and add style components animations

so we will import keyframes using this line
import styled, { keyframes } from ‘styled-components’;

then we will create a new component for animation name

const rotate360 = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;

and we will use this animation name instead of App-logo-spin in HeaderImage component and add the new animation name with this way

const HeaderImage = styled.img`
animation: ${rotate360} infinite 20s linear;
height: 40vmin;
`;

then we will remove all styles from app.css and will remove the import of app.css from app.js file, so the file will look like

  • How to use pseudo-classes like hover, focus, nth-child, first-child and so on
  • Styled Components and Props
  • InjectGlobal
  • Attrs
  • Extend
  • withComponent
  • Media Query

let’s update our above example with adding hover in the Header component and when hovering on it, its background will change to be skyblue for example

if you used one of the preprocessors before like SASS / LESS for sure you used ampersand character (&) so in styled components we can use some features from preprocessors like nesting and ampersand character (&)

and in Styled Components, we used, stylis, the preprocessor that supports scss-like syntax for automatically nesting styles.

so you can just add it like:

const Header = styled.header`
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
&:hover{
background: skyblue;
}
`;

so when hovering it will look like:

so easy right?!

Styled Components and Props

One of the great things on styled-components is that they allow you to change styles of your components according to its props.

for example, let’s change the background-color of the Header if we pass primary prop to it, so the default background-color will be #282c34 and if primary prop has existed the background-color will be for example red

so now Header component will be like <Header primary> and component style will look like

const Header = styled.header`
background-color: ${props => props.primary ? 'red' : '#282c34'};
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
&:hover{
background: skyblue;
}
`;

so I just checked the props if there is primary prop the background-color will be red else the background-color will be #282c34

and now it will look like:

so props in styled components work like Modifers

injectGlobal

NOTE

The injectGlobal API was removed and replaced by createGlobalStyle in styled-components v4.

A helper method to write global CSS. It does not return a component but adds the styles to the stylesheet directly.

we will import injectGlobal from styled components using this line

import styled, { keyframes, injectGlobal } from 'styled-components';

then we will add our global styles to the body

injectGlobal`
body{
height: 2000px;
color: #000;
margin: 0;
}
`;

Attrs

This is a method that attaches some props to a styled component and its object accepts the following values:

Prop Value: These can be of any type, except functions. They’ll stay static and will be merged into the existing component props.

Prop Factor: A function that receives the props that are passed into the component and computes a value, that is then going to be merged into the existing component props.

const Input = styled.input.attrs({
type: 'text',
size: props => (props.small ? 5 : undefined ),
placeholder: 'Enter Your Name',
})`
border-radius: 5px;
border: 3px solid blue;
display: block;
margin: 20px auto;
padding: 10px;
font-size: 15px;
color: blue;

::placeholder {
color: blue;
}
`;

and attach the component in the render method like

<Input />
<Input small />

and the output will be something like that:

Extend

This is a method that creates a new StyledComponent and extends its rules.

for example, we have 2 buttons and they have the same styles but one of them has a different border-color

const Button = styled.button`
padding: 10px
border: 3px solid black;
border-radius: 5px;
background-color: white;
display: inline-block;
margin: 0 auto 20px;
`;
const GreenButton = Button.extend`
border-color: green
`;

and attach button component in render method like:

<Button>Default Button</Button>
<GreenButton>Green Button</GreenButton>

so it will look like:

withComponent

This is a method that creates a new StyledComponent with a different tag or component applied to it, but all the same rules of the one it’s called on.

we will use the prev example of Button to use with.Component with an anchor tag

const LinkAsButton = Button.withComponent('a');

and attach it in render method like

<LinkAsButton href="https://www.google.com"> Google Website </LinkAsButton>

and it will look like

and in Styled Component V4 you can use as attribute instead of withComponent like:

<Button as="a">Link Button</Button>

Media Query

we will add a small media query style in the header to changebackground-colorto be black in devices that smaller than 420px

const Header = styled.header`
background-color: ${props => props.primary ? 'red' : '#282c34'};
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;

&:hover{
background: skyblue;
}

@media screen and (max-width: 420px){
background-color: black;
}
`

and it will look like:

Finally you can find the final code in sandbox

--

--