Styled Components Universe — Part 1/3
Hey young grasshoppers! As I mentioned in another article, today I'm going to dive a little deeper into this wonderful library that is Styled Components. I'll split this topic into three articles: in this one I'll cover some of styled's features, in the second I'll talk about testing (don't take this order into account when building an application), and in the last one I'll explain best development practices (focused on styled components, of course).
Let's get into part one, Styled Components :)

Round 1 — Fight!
Installation
npm install --save styled-components
Easier than it sounds.
Styled components creates tagged template literals to style your component, meaning we are defining our style and as a result creating our React component — that's beautiful :)
Broadly speaking, it's a library that uses the power of CSS with JS to create primitive components in React!
Primitive elements:
</h1>, </span>, </form>, </input>
Example of a created component:
import styled from 'styled-components'
// Button Create
const Button = style.button`
font-size: 12px;
background: transparent;
border: 1px solid #CCC;
color: #ccc;
`
// Icon Create
const Icon = styled.i`
vertical-align: middle;
color: ${props => props.active ? '#5cb85c' : ''}
`
Then just import it and use the component:
<Button />, <Icon />, <Modal opened size="500px" />
Simple, right!?
Props
Now the "magic" begins… You can pass all React component props into the styled template \o/. It's JS, remember!? ;)
Here's an example:
import styled from 'styled-components'
export const StyledButton = styled.button`
height: ${props => props.size};
width: ${props => props.size};
background: ${
(props) =>
props.close ? '#9B9B9B' :
props.draft ? '#F0AD4E' :
props.theme.primary
};
white-space: nowrap;
&:focus {
background: ${props => props.theme.primary};
color: #FFF;
}
&:disabled {
color: #EFEFEF;
background: #CCC;
cursor: not-allowed;
}
`
What's the advantage of this?
You simply have the full power of JS at your fingertips, being able to create functions, conditionals, merge properties, use defaultProps, propTypes, and enable the lint for styled itself :). Everything JS offers, in your CSS — combining the power of both.
Another great thing is the reduction of code. Before, it was necessary to create countless classes with minor differences — this happened a lot with color variations and it was terrible. A simple example is creating a button with variations: if the dev team isn't well-aligned, we can end up with some pretty peculiar situations, like below:
.big-button, .big-button:focus {
height: 259px;
font-size: 55px;
padding: 0 20px;
background: #00afe0;
border: none;
&:hover {
background-color: #00A8D5;
}
}
.button-secondary {
background: #efefef;
}
.button-danger {
background: #aacf3r;
}
.button-primary, .button-primary:focus {
background: #00afe0;
color: #FFF;
border: none;
&:hover {
color: #FFF;
background-color: #00A8D5;
}
}
This can be avoided by simply passing props, handling all the control and creating the necessary variations. This results in a smaller bundle and a clearer logic about what the component does.
Imagine medium and large-scale projects with multidisciplinary teams — creating and maintaining CSS can become quite complex.
Co-creator Max Stoiber says:
The basic idea of styled-components is to enforce best practices by removing the mapping between styles and components.**
Creating components
As already mentioned, it's possible to create primitive components, passing all HTML props like onClick, id, name, etc…
To create a component, simply import styled and specify the component to be created, for example:
-
input
import styled from 'styled-components'export const Input = styled.input`// code` -
div
import styled from 'styled-components'export const Wrapper = styled.div`// code``
Easy ;)
Theme
Theme creation is one of the things I find most amazing — I can pass a theme and all child elements will receive that property. Styled components has full theme support by exporting ThemeProvider, allowing multiple levels of depth.
Below is an example I took from the styled components website where a button is being created with theme props coming from ThemeProvider:
// Define our button, but with the use of props.theme this time
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're 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>
);
It's also possible to pass properties contextually, as functions. These functions will receive the parent theme — another ThemeProvider that is higher up in the component tree.
The example below renders a styled button and a second one with inverted colors. The function inverts the received theme, creating a new button. This example is also from the official site:
// Define our button, but with the use of props.theme this time
const Button = styled.button`
color: ${props => props.theme.fg};
border: 2px solid ${props => props.theme.fg};
background: ${props => props.theme.bg};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border-radius: 3px;
`;
// Define our `fg` and `bg` on the theme
const theme = {
fg: 'palevioletred',
bg: 'white'
};
// This theme swaps `fg` and `bg`
const invertTheme = ({ fg, bg }) => ({
fg: bg,
bg: fg
});
render(
<ThemeProvider theme={theme}>
<div>
<Button>Default Theme</Button>
<ThemeProvider theme={invertTheme}>
<Button>Inverted Theme</Button>
</ThemeProvider>
</div>
</ThemeProvider>
);
Theme with HOC
If needed, it's also possible to use the theme with HOC (higher order component), without needing styled. Example taken from the site:
import { withTheme } from 'styled-components'
class MyComponent extends React.Component {
render() {
console.log('Current theme: ', this.props.theme);
// ...
}
}
export default withTheme(MyComponent)
This works best with large components ;). Really reconsider whether this approach is necessary.
The THEME prop
The theme can also be passed using the theme prop.
This can be done in cases where there is no ThemeProvider, as shown below:
// Define our button
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};
`;
// Define what main theme will look like
const theme = {
main: 'mediumseagreen'
};
render(
<div>
<Button theme={{ main: 'royalblue' }}>Ad hoc theme</Button>
<ThemeProvider theme={theme}>
<div>
<Button>Themed</Button>
<Button theme={{ main: 'darkorange' }}>Overidden</Button>
</div>
</ThemeProvider>
</div>
);
Helpers
Helpers, as the name suggests, are aids to improve your CSS development. Some helpers available in styled components:
-
CSS
-
Keyframes
-
injectGlobal
-
withTheme
They are very important and widely used — such as css, where you can create a template literal using interpolation, for example:
import styled, { css } from 'styled-components';
const complexMixin = css`
color: ${props => props.whiteColor ? 'white': 'black'}
`;
const StyledComp = styled.div`
/* This is an example of a nested interpolation */
${props => props.complex ? complexMixin : 'color: blue;'}
`;
To see the rest, click here ;)
CSS Support
Well, I left the support section for last because I believe many people who are starting out with styled components have this question: "what about CSS support?"
Take it easy, young grasshoppers — the support remains the same. It's all CSS, beautiful!
Therefore, all features available in CSS also exist in styled components, since an actual stylesheet is created and not inline CSS.
Here is a note from the development team on this subject:
Within a styled component, we support all of CSS plus nesting. Since we generate an actual stylesheet and not inline styles, whatever works in CSS works in styled-components!
Well, I talked a bit more about this powerful tool that is Styled Components, covering some of its features and component creation, as well as its behavior.
Now, as I promised, in the next article in the Styled Components series I'll talk about testing!
Ah… Before wrapping up this part, I just want to leave a tip — it's possible to create and use the same components in REACT NATIVE! But that's a topic for another article…
Sources:
