Only article you need on Styled Components in ReactJs

Vivek Singh
7 min readNov 19, 2021

Styled-components is a CSS in JS styling framework that uses tagged template literals in JavaScript and the power of CSS to provide a platform that allows you to write actual CSS to style React components.

  1. Example with Syntax Explanation
  2. Installation
  3. Inherit Styling
  4. Props in Styled Components
  5. The As Polymorphic prop
  6. Global Styling
  7. Why use Styled Components ?
  8. Internal Working of Styled Components
  9. References

Example with Syntax Explanation :

import React from 'react'
import styled from 'styled-components'
const Header = styled.h1`
color: yellow;
`
function App() {
return(
<Header>
React Header Text
</Header>
)
}

styled.h1 indicates that we want to use a H1 tag as HTML element to show the React Header text. All the CSS properties are passed inside the backticks.

Traditionally, this is how we generally use CSS in our application :

render() {
return <span className="menu navigation-menu">Menu</span>
}

Installation

yarn add styled-componentsnpm i styled-components

Inherit styling

const Header = styled.h1 `   color: yellow;`const Footer = styled(header) `    font-style: italic;`

With this, now Footer is a h1 tag with color yellow and font-style as italic.

Props in Styled Components

We can use props in styled-components, e.g. to display CSS-styles based on certain conditions. Inside the backticks, in JavaScript(marked in bold), we can pass the $ sign to dynamic code, and thus return a CSS value based on the props passed from JavaScript code.

const Text = styled.p`
visibility: ${props => (
props.show? "visible":"hidden")
};

`
function App() {
return(
<Text show={true}>Hey there! This is Michael Scott from The Office</Text>
)
}

Based on show prop’s value, the visibility property will either be true or false. Here the visibility will be true since true is passed as the prop value.

The As Polymorphic prop

If you want to keep all the styling you’ve applied to a component but just switch out what’s being ultimately rendered (be it a different HTML tag or a different custom component), you can use the “as” prop to do this at runtime.

const StyledContainer = styled.section`
max-width: 1024px;
padding: 0 20px;
margin: 0 auto;
`;
// Inherit StyledContainer in StyledSmallConatiner
const StyledSmallContainer = styled(StyledContainer)`
padding: 0 10px;
`;
function Home() {
return (
<StyledContainer>
<h1>The secret is to be sad</h1>
</StyledContainer>
);
}
function Contact() {
return (
<StyledSmallContainer>
<h1>The road not taken</h1>
</StyledSmallContainer>
);
}

If we wanted to use a different HTML element for <StyledSmallContainer> ; this is how we would do it, by passing the HTML element inside ‘as’.

function Home() {
return (
<StyledContainer>
<h1>Head in the clouds; feet on the ground.</h1>
</StyledContainer>
);
}
function Contact() {
return (
<StyledSmallContainer as="div">
<h1>Keep me where the light is!</h1>
</StyledSmallContainer>
);
}

GLOBAL STYLING

A helper function to generate a special styled component that handles global styles. Normally, styled components are automatically scoped to a local CSS class and therefore isolated from other components. In the case of createGlobalStyle, this limitation is removed and things like CSS resets or base stylesheets can be applied.

import React, { Fragment } from 'react';
import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
padding: 0;
background: teal;
font-family: Open-Sans, Helvetica, Sans-Serif;
}
`;
function App() {
return (
<Fragment>
<GlobalStyle />
Your Content
</Fragment>
);
}

Why use Styled Components ?

  1. Everything is Component. Even your styles.

Styled Components help keep the concerns of styling and element architecture separated and make components more readable.
Furthermore, when you have components that rely on JavaScript for their style, Styled Components gives control of those states back to CSS instead of using a multitude of conditional class names.

// The render method of some component
render() {
const style = {
color: `${this.props.themeColor}`,
}
const hoverStyle = {
color: `${this.props.hoverThemeColor}`
}
return (
<button
onMouseEnter={this.handleHover}
onMouseOut={this.handleHover}
style={this.state.isHovered ? hoverStyle : style}
>
Click Me!
</button>
);
}

Same code using styled components :

import styled from 'styled-components';
const BrandedButton = styled.button`
color: ${props => props.themeColor};
&:hover {
color: ${props => props.themeHoverColor};
}
`
render(){
return (
<BrandedButton themeHoverColor="pink" themeColor="blue" >
Click Me!
</BrandedButton>
);
}

Instead of relying on two separate style objects and having to use React event handlers to setup a simple hover state, we use a styled component. This makes it easy to inject values that only exist in JavaScript into our CSS while still allowing CSS to handle the various UI states.

2. You can use Jest Styled Component to test the mandate css styles for your components .

https://github.com/styled-components/jest-styled-components

expect(div).toHaveStyleRule(‘color’, yellow);

3. Theming support

styled-components has full theming support by exporting a <ThemeProvider> wrapper component. This component provides a theme to all React components underneath itself via the context API. In the render tree all styled-components will have access to the provided theme, even when they are multiple levels deep.

const Button = styled.button`
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border-radius: 3px;
/* Color the border and text with theme.main */
color: ${props => props.theme.main};
border: 2px solid ${props => props.theme.main};
`;
// We are passing a default theme for Buttons that aren't wrapped in the ThemeProvider
Button.defaultProps = {
theme: {
main: "palevioletred"
}
}
// Define what props.theme will look like
const theme = {
main: "mediumseagreen"
};
render(
<div>
<Button>Normal</Button>
<ThemeProvider theme={theme}>
<Button>Themed</Button>
</ThemeProvider>
</div>
);

The ThemeProvider is particularly useful when building a use case where we need to use an existing functional logic and just need different styling with elements. We can customize certain stylistic elements using Theme.

4. Better visibility of code

If you have worked with a large web application, you can attest to the fact that the CSS files begin to get bulky, clumsy, and complex. One great solution to this is the introduction of SASS. Although SASS helps, you’ll eventually deal with the same issue due to the sheer number of SCSS files a project can have. Even the abstraction starts to become complex in itself.

With styled-components, the UI design’s focus shifts from merely styling HTML elements or React components through className to defining styled components that contain their own styles and are easily reusable across the entire project.

5. No class name bugs
styled-components generates unique class names for your styles. You never have to worry about duplication, overlap or misspellings.

6. Dynamic styling
Adapting the styling of a component based on its props or a global theme is simple, dynamic and intuitive without having to manually manage dozens of classes. This control using props, theme, and as polymorphic group gives us flexibility.

7. Painless maintenance
You never have to hunt across different files to find the styling affecting your component, so maintenance is a piece of cake no matter how big your codebase is. Everything is inside the same file.

There are a host of CSS-in-JS frameworks out there; alternatives : Emotion, JSS, Radium, Aphrodite.

Internal working of styled components
Template Literals are the underlying concept in styled components. We know template literals are used to concatenate strings.

const expressions = 'dynamic values';
const example = `I can contain ${expressions}`;
console.log(example); // >> I can contain dynamic values

The usage can be extended to more use cases.

const printStaticMessage = () => {
console.log('My static message');
}

We can invoke the above function in 2 ways :

printStaticMessage(); // >>> My static message
printStaticMessage``; // >>> My static message

Notice that each invocation generated the same result. So, we can conclude that Tagged Templates are just an alternative way to invoke a function.

Use case :

const printArguments = (…args) => { console.log(…args); }
const var1 = “my”;
const var2 = “message”
printArguments`This is ${var1} custom ${var2}!`;
// [“This is “,” custom “,”!”],
// “my”,
// “message”

Similarly, styled components actually uses higher order component approach, similar to this :

const myStyled = (TargetComponent) => ([style]) => class extends React.Component {
componentDidMount() {
this.element.setAttribute('style', style);
}
render() {
return (
<TargetComponent {…this.props} ref={element => this.element = element } />
);
}
};
const Button = myStyled('button')`
color: coral;
padding: 0.25rem 1rem;
border: solid 2px coral;
border-radius: 3px;
margin: 0.5rem;
font-size: 1rem;
`;

Note : This topic of internal working maybe a gray area because it needs more explanation. I found this blog which you can refer to understand this concept better.

References:

https://styled-components.com/

https://blog.logrocket.com/benefits-using-styled-components-react/

https://medium.com/swlh/styled-components-e29204a2fb1a

https://scalablecss.com/styled-components-global-styles/

https://rangle.io/blog/styled-components-styled-systems-and-how-they-work/

Conclusion :

Hope this article was helpful. Please follow and hit the clap button to be in touch. Happy learning. Cheers!

--

--

Vivek Singh

Software Developer. I write about Full Stack, NLP and Blockchain. Buy me a coffee - buymeacoffee.com/viveksinless