styled
is a way to create React components that have styles attached to them. It's available from @emotion/styled. styled
was heavily inspired by styled-components and glamorous.
Styling elements and components
styled
is very similar to css
except you call it with an html tag or React component and then call that with a template literal for string styles or a regular function call for object styles.
import styled from '@emotion/styled'
const Button = styled.button`
color: turquoise;
`
render(<Button>This my button component.</Button>)
(Edit code to see changes)
Changing based on props
Any interpolations or arguments that are functions in styled
are called with props
, this allows you to change the styles of a component based on the props.
import styled from '@emotion/styled'
const Button = styled.button`
color: ${props => (props.primary ? 'hotpink' : 'turquoise')};
`
const Container = styled.div(props => ({
display: 'flex',
flexDirection: props.column && 'column'
}))
render(
<Container column>
<Button>This is a regular button.</Button>
<Button primary>This is a primary button.</Button>
</Container>
)
(Edit code to see changes)
Styling any component
styled
can style any component as long as it accepts a className
prop.
import styled from '@emotion/styled'
const Basic = ({ className }) => <div className={className}>Some text</div>
const Fancy = styled(Basic)`
color: hotpink;
`
render(<Fancy />)
(Edit code to see changes)
Change the rendered tag using withComponent
Sometimes you want to create some styles with one component but then use those styles again with another component, the withComponent
method can be used for this. This was inspired by styled-components' withComponent
.
import styled from '@emotion/styled'
const Section = styled.section`
background: #333;
color: #fff;
`
const Aside = Section.withComponent('aside')
render(
<div>
<Section>This is a section</Section>
<Aside>This is an aside</Aside>
</div>
)
(Edit code to see changes)
Targeting another emotion component
Similar to styled-components, emotion allows for emotion components to be targeted like regular CSS selectors when using @emotion/babel-plugin.
import styled from '@emotion/styled'
const Child = styled.div`
color: red;
`
const Parent = styled.div`
${Child} {
color: green;
}
`
render(
<div>
<Parent>
<Child>Green because I am inside a Parent</Child>
</Parent>
<Child>Red because I am not inside a Parent</Child>
</div>
)
(Edit code to see changes)
Component selectors can also be used with object styles.
import styled from '@emotion/styled'
const Child = styled.div({
color: 'red'
})
const Parent = styled.div({
[Child]: {
color: 'green'
}
})
render(
<div>
<Parent>
<Child>green</Child>
</Parent>
<Child>red</Child>
</div>
)
(Edit code to see changes)
Object styles
import styled from '@emotion/styled'
const H1 = styled.h1(
{
fontSize: 20
},
props => ({ color: props.color })
)
render(<H1 color="lightgreen">This is lightgreen.</H1>)
(Edit code to see changes)
This API was inspired by glamorous. ❤️
Customizing prop forwarding
By default, Emotion passes all props (except for theme
) to custom components and only props that are valid html attributes for string tags. You can customize this by passing a custom shouldForwardProp
function. You can also use @emotion/is-prop-valid
(which is used by emotion internally) to filter out props that are not valid as html attributes.
import isPropValid from '@emotion/is-prop-valid'
import styled from '@emotion/styled'
const H1 = styled('h1', {
shouldForwardProp: prop => isPropValid(prop) && prop !== 'color'
})(props => ({
color: props.color
}))
render(<H1 color="lightgreen">This is lightgreen.</H1>)
(Edit code to see changes)
Composing dynamic styles
You can create dynamic styles that are based on props and use them in styles.
import styled from '@emotion/styled'
import { css } from '@emotion/react'
const dynamicStyle = props =>
css`
color: ${props.color};
`
const Container = styled.div`
${dynamicStyle};
`
render(<Container color="lightgreen">This is lightgreen.</Container>)
(Edit code to see changes)
as
prop
To use styles from a styled component but change the element that's rendered, you can use the as
prop.
import styled from '@emotion/styled'
const Button = styled.button`
color: hotpink;
`
render(
<Button as="a" href="https://github.com/emotion-js/emotion">
Emotion on GitHub
</Button>
)
(Edit code to see changes)
This API was inspired by styled-components. ❤️
The as
prop is only used by styled when it's not forwarded to the underlying element. By default, this means that the as
prop is used for html tags and forwarded for components. To change this, you can pass a custom shouldForwardProp
which returns true
for 'as'
to forward it or returns false
for 'as'
to use it and not forward it.
Nesting components
We can nest selectors using &
:
import styled from '@emotion/styled'
const Example = styled('span')`
color: lightgreen;
& > strong {
color: hotpink;
}
`
render(
<Example>
This is <strong>nested</strong>.
</Example>
)
(Edit code to see changes)