With styled components we can attach css/sass to a react component via JS. Styled can take props and make conditional styling via JS. Styles are scoped Everything is located in one file Installation Firstly we need to install library via npm npm install --save styled-components Then add it to our file import styled from 'styled-components' Basic usage
import React from 'react'
import styled from 'styled-components'
const Basic = () => <Div1>I am div</Div1>
const Div1 = styled.div`
font-size: 20px;
color: tomato;
`
<Basic />
Styles in object
const StylesInObject = () => <DivXXX>I am div</DivXXX>
const DivXXX = styled.div({
fontSize: '20px',
color: 'tomato'
})
<StylesInObject />
Supports SCSS
const ScssSupport = () => <Div2><span>we</span><span>are</span><span>spans</span></Div2>
const Div2 = styled.div`
background: yellow;
span {
background: black;
color: white;
margin: 5px;
}
`
<ScssSupport />
Pass CSS prop to styled We can pass a string as CSS via props to styled
const PassCssProperty = () => <Div3 fontWeight={800}>I am div</Div3>
const Div3 = styled.div`
font-size: 20px;
color: tomato;
font-weight: ${props => props.fontWeight};
`
<PassCssProperty />
Pass whole CSS as string We can pass whole CSS string to styled component. Same result as above.
const PassWholeCssString = () => (
<DivADFAG styles={'font-size: 20px;color: tomato;font-weight: 800;'}>I am div</DivADFAG>
)
const DivADFAG = styled.div`
${props => props.CSS}
`
<PassWholeCssString />
Pass part of CSS as string For example we may add additional CSS rules to existing ones.
const PassPartOfCssAsString = (props) => <Div6 styles={props.css}>I am div</Div6>
const Div6 = styled.div`
font-size: 20px;
${props => props.css};
`
<PassPartOfCssAsString styles='color: brown; border: 1px solid grey;' />
Pass all props All component's props falls into a styled component by default.
const DoNotSpecifyProp = () => <Div5>I am div</Div5>
const Div5 = styled.div`
font-size: 20px;
color: ${props => props.color || 'tomato'};
`
<DoNotSpecifyProp color="orange" />
Extend existing styled component
const ExtendExistingStyledComponent = () => <Div7>I am div</Div7>
const Div7 = styled(Div1)`
border: 1px dotted tomato;
border-radius: 10px;
`
<ExtendExistingStyledComponent />
Pass props to the element's attributes
const PropsInAttributes = () => <MyImg src='/imgs/va/img99.jpg' width='50%' />
const MyImg = styled.img.attrs(props => ({
src: props.src || props.path,
alt: 'some text',
width: props.width || '100%',
height: 'auto',
}))`
border: 4px solid tomato;
@media screen and (max-width: 800px) {
min-width: 100%;
}
`
<PropsInAttributes />
Conditional style
const ConditionalStyles = () => {
const [toggleState, setToggleState] = React.useState(true)
const changeColor = () => setToggleState(!toggleState)
return (
<>
<Div9 toggleState={toggleState}>I am div</Div9>
<button onClick={changeColor}>Change color</button>
</>
)
}
const Div9 = styled.div`
background: ${props => props.toggleState ? 'tomato' : 'yellow'};
`
<ConditionalStyles />
Animation Animation in styled components needs a special helper keyframes from the library. Keyframes basic usage We just use keyframes variable inside our styled component's string literals.
import styled, { keyframes } from 'styled-components'
const rotate = keyframes`
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
`;
const DivRotate = styled.div`
display: inline-block;
margin: 5px;
padding: 5px;
background: tomato;
animation: ${rotate} 2s linear infinite;
`;
<DivRotate>Hello</DivRotate>
Hello Start animation by adding keyframes name We pass the state into styled component and toggle animation name on its change. When animation ends animation name may be removed with onAnimationEnd event.
import React, { useState } from 'react';
import styled, { keyframes } from 'styled-components';
const shakeAnimation = keyframes`
0% { transform: translateX(0) }
10% { transform: translateX(5px) }
30% { transform: translateX(0) }
50% { transform: translateX(5px) }
70% { transform: translateX(0) }
90% { transform: translateX(5px) }
100% { transform: translateX(0) }
`
const DivShake = styled(DivRotate)`
animation: ${props => props.animateNow ? shakeAnimation : ''} .3s ease-in-out;
cursor: pointer;
`
function Basic() {
const [animationState, setAnimationState] = useState(false)
const startAnimation = () => setAnimationState(true)
const endAnimation = () => setAnimationState(false)
return <>
<DivShake
onClick={startAnimation}
animateNow={animationState}
onAnimationEnd={endAnimation}
>
Click me to shake
</DivShake>
</>
}
<KeyFramesNameToStartAnimation />
Start animation by adding class name
const popAnimation = keyframes`
from { transform: scaleY(0); }
to { transform: scaleY(1); }
`
const DivPop = styled(DivShake)`
animation: 'none';
&.animationClass {
animation: ${popAnimation} 0.5s ease;
}
`
function ScssSupport() {
const [animationState, setAnimationState] = useState(false)
const startAnimation = () => setAnimationState(true)
const endAnimation = () => setAnimationState(false)
return <>
<DivPop
className={animationState ? 'animationClass' : ''}
onClick={startAnimation}
onAnimationEnd={endAnimation}
>
Click me to pop out
</DivPop>
</>
<ClassNameToStartAnimation />
}
Style existing component Any existing component can be styled as long as it has className prop.
function ExistingComponent({ className }) {
return (
<div className={className}>
I am div
</div>
)
}
const StyledExistingComponent = styled(ExistingComponent)`
color: red;
font-weight: bold;
`
<StyledExistingComponent />
Theming with wrapper
import styled, { ThemeProvider } from 'styled-components'
const theme = {
redish: '#ff7979'
}
const Button = styled.button`
color: ${props => props.theme.redish};
`
function ComponentUsesThemeWrapper(props) {
return (
<div>
<ThemeProvider theme={theme}>
<Button>Themed</Button>
</ThemeProvider>
</div>
)
}
<ComponentUsesThemeWrapper />
Theme values outside styled components
const theme2 = {
grey: 'grey',
white: 'white'
}
function ThemeOutsideStyledComponent() {
const theme = useTheme()
return (
<div style={{ background: theme.grey, color: theme.white }}>
I am div
</div>
)
}
<ThemeProvider theme={theme2}>
<ThemeOutsideStyledComponent />
</ThemeProvider>
In NextJs In NextJs styled components requires additional configuration.