CSS in JS. Styled components. Quick start

Instalation

npm install styled-components

Import

import styled from 'styled-components';

Components implementation

For element creation use special syntax:

  1. Camel case name for Component
  2. styled.[tag name]`[css]`

Example creation component with name Li and tag name li

const Li = styled.li`
display: flex;
list-style-type: none;
text-align: left;
width: 100%;
-webkit-transition: all .3s ease;
-moz-transition: all .3s ease;
-o-transition: all .3s ease;
-ms-transition: all .3s ease;
transition: all .3s ease;
padding-right: 10px;
`;

Usinge in React

export default class List extends React.PureComponent {
    render() {
return (
<Select>
<Li>{`First item`}</Li>
<Li>{`Second item`}</Li>
</Select>
)
}
}

CSS tricks in styled components

Use ampersands (&) for pointing that you want get replaced by our generated, unique classname for than styled, making it easy to have complex logic.

const Example = styled.div`
/* all declarations will be prefixed */
padding: 2em 1em;
background: papayawhip;

/* pseudo selectors work as well */
&:hover {
background: palevioletred;
}

/* media queries are no problem */
@media (max-width: 600px) {
background: tomato;

/* nested rules work as expected */
&:hover {
background: yellow;
}
}

> p {
/* descendant-selectors work as well, but are more of an escape hatch */
text-decoration: underline;
}

/* Contextual selectors work as well */
div.test & {
display: none;
}
`;

render(
<div className='test'>
<Example>
<p>Hello World!</p>
</Example>
</div>
);

Overriding styles of other(child) components

This flow using for styled components only!!!

const Block = styled.div`
width:100%;
`;
const Header = styled.h2`
color: black;
${Block}:hover & {
color: red;
}
`;

Description: You have Block component as parent and Header component as child. In normal state Header have black color, when mouse pointer hover over Block components, Header color will be red.

You can use overriding styles not only with pseudo selecors but in normal state.

const Header = styled.h2`
color: black;
`;
const Block = styled.div`
width:100%;
${Header} {
color: red;
}
`;

Header color defined as black but if Block component will be parent for Header then Header color will be red.

Overriding styles of other(child) non styled components

Next code thrown

class A extends React.Component {
render() {
return <div />;
}
}

const B = styled.div`
${A} {
}
`;

It caused by using non styled component A — its React Component!!!

For fix you should wrap to styled component

class A extends React.Component {
render() {
return <div className={this.props.className} />;
}
}

const StyledA = styled(A)``;

const B = styled.div`
${StyledA} {
}
`;

Theme

Define theme styles

export const myTheme = {
font: {
baseSize: '14px',
mainColor: '#FF0000',
titlesColor: '#00FF00',
hoverColor: '#0000FF'
},
colors: {
backgroundColor: '#000000',
navigationBarColor: '#FFFFFF',
}
};

Set theme styles via ThemeProvider

import React from 'react';
import { render } from 'react-dom';
import { ThemeProvider } from 'styled-components';
import { myTheme } from './themes';
import { List} from './components/List';
render(
<ThemeProvider theme={myTheme}>
<List />
</ThemeProvider>,
document.getElementById('root')
);

Theme component using

ThemeProvider pass theme in props to all components

import styled from 'styled-components';
export const Input = styled.input`
width: 100%;
font-size: ${props => props.theme.font.baseSize};
color: ${props => props.theme.font.titlesColor};
background-color: ${props => props.theme.colors.backgroundColor};
padding: 5px;
outline: none;
&::placeholder{
color: ${props => props.theme.font.mainColor};
}
`;

Mixins

Defining mixin

import { css } from 'styled-components';
export const mixins = {
hoverState: () => css`
&:hover {
background-color: ${props => props.theme.colors.hoverColor};
}`,
activeState: () => css`
&:active {
background-color: ${props => props.theme.colors.pressedColor};
}`
};

Mixin usage

import styled from 'styled-components';
import { mixins} from './styles/mixins';
export const Input = styled.input`
${mixins.hoverState``};
${mixins.activeState``};
width: 100%;
font-size: 1em;
padding: 5px;
outline: none;
`;

Refference to the DOM

Access to the DOM in styled components using “innerRef” prop, not “ref”

export default class App extends React.PureComponent {
input = null;
    render() {
return (
<Input innerRef={ref => this.input = ref} />
)
}
}

Condition in CSS

import React from 'react';
import styled from 'styled-components';
const List = styled.ul`
width: 100%;
display: ${props => props.open? 'block': 'none'};
font-size: 1em;
padding: 5px;
outline: none;
`;
export default class App extends React.PureComponent {
render() {
return (
<List open={false} />
)
}
}

Extending styles in existed components

If you want extend styled component you should use extend method

const Button = styled.button`
width: 100%;
background-color: #00000;
font-size: 1em;
padding: 5px;
outline: none;
`;
const RedButton = Button.extend`
background-color: red;
`;

If you want extend styles of component from another file or a third party library, prefer to use styled(Component)

import Button from './Button'; // React Component
const RedButton = styled(Button)`
background-color: red;
`;

Replace tag and reuse same styles

For replacing tag and using same styles you should use .withComponent(Component) method which returns styled component

const Button = styled.button`
width: 100%;
background-color: #00000;
font-size: 1em;
padding: 5px;
outline: none;
`;
const Link = Button.withComponent('a');

or with styled component

const A = styled.a`
color:red;
`;
const Button = styled.button`
width: 100%;
background-color: #00000;
font-size: 1em;
padding: 5px;
outline: none;
`;
const Link = Button.withComponent(A);

If you want replace tag and use additional styles you should use .extend method.

const Link = Button.withComponent('a');
const OtherLink = Link.extend`
color: green;
`;
render(
<div>
<Link>First link</link>
<OtherLink>Second link</OtherLink>
</div>
)

Set additional attributes (or attributes)

import styled from 'styled-components';
const Checkbox = styled.input.attrs({
type: 'checkbox'
})
`
margin: 0 !important;
cursor: pointer;
`;

Animations

import {keyframes} from 'styled-components';
const rotate360 = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;

const Rotateable = styled.div`
animation: ${rotate360} 2s linear infinite;
`;

render(
<Rotateable>Hi there!</Rotateable>
);

Global styles

For defining global styles you should use injectGlobal method

import { injectGlobal } from 'styled-components';

injectGlobal`
body {
margin: 0;
padding: 0;
}
`;

Check is styled component object

For identify styled components you should use isStyledComponent

import React from 'react';
import { isStyledComponent } from 'styled-components';
import MaybeStyledComponent from './somewhere-else';

const shouldUseInnerRef = isStyledComponent(MaybeStyledComponent);

class MyComponent extends React.PureComponent {
render() {
return React.createElement(
MaybeStyledComponent, {
[shouldUseInnerRef ? 'innerRef' : 'ref']: node => { this.el = node; }
}
)
}
}

Force passing theme as props to styled components and non styled components (React)

For using theme out of ThemeProvider or using theme in React Components you should use method withTheme which returns wrapped styled component with theme props

import { withTheme } from 'styled-components'

class MyComponent extends React.Component {
render() {
<div> Hello </div>
}
}

export default withTheme(MyComponent)