emotion
Without a React Framework
-
Installation
npm i @emotion/css or yarn add @emotion/css -
Description
- It doesn't require any additional setup, a babel plugin, or other configuration.
- It supports auto vendor-prefixing, nested selectors, and media queries.
- auto vendor-prefixing
- webkit- supported by OPERA, SAFARI, GOOGLE CHROME
- moz- supported by FIREFOX
- ms- supported by EDGE/INTERNET EXPLORER
- auto vendor-prefixing
- When you use the css function, a classname is generated automatically, and with cx it even supports combining multiple classes.
- However, additional work is required for server-side rendering.(https://emotion.sh/docs/ssr#api)
import { css, cx } from '@emotion/css'; const color = 'white'; render( <div className={css` padding: 32px; background-color: hotpink; font-size: 24px; border-radius: 4px; &:hover { color: ${color}; } `} > Hover to change color. </div>, );
With a React Framework
-
@emotion/react
-
Installation
npm i @emotion/react or yarn add @emotion/react -
Description
- Supports the css prop
- It supports auto vendor-prefixing, nested selectors, and media queries.
- auto vendor-prefixing
- webkit- supported by OPERA, SAFARI, GOOGLE CHROME
- moz- supported by FIREFOX
- ms- supported by EDGE/INTERNET EXPLORER
- auto vendor-prefixing
- It reduces boilerplate code when composing components and applying styles.
- It supports auto vendor-prefixing, nested selectors, and media queries.
- No separate configuration is needed when performing server-side rendering.
- We recommend using ESLint to properly apply the recommended patterns and configuration.
import { css } from '@emotion/react'; const danger = css` color: red; `; const base = css` background-color: darkgreen; color: turquoise; `; render( <div> <div css={base}>This will be turquoise</div> <div css={[danger, base]}> This will be also be turquoise since the base styles overwrite the danger styles. </div> <div css={[base, danger]}>This will be red</div> </div>, ); - Supports the css prop
-
-
@emotion/styled
-
Installation
npm i @emotion/styled @emotion/react or yarn add @emotion/styled @emotion/react -
Description This is a package for users who prefer a styling approach like styled.div when creating components.
import styled from '@emotion/styled'; const Button = styled.button` padding: 32px; background-color: hotpink; font-size: 24px; border-radius: 4px; color: black; font-weight: bold; &:hover { color: white; } `; render(<Button>This my button component.</Button>); -
Styling elements and components
import styled from '@emotion/styled'; const Button = styled.button` color: turquoise; `; render(<Button>This my button component.</Button>); -
Changing based on props When you want to change a component's styles based on 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>, ); -
classname styling through component inheritance
import styled from '@emotion/styled'; const Basic = ({ className }) => <div className={className}>Some text</div>; const Fancy = styled(Basic)` color: hotpink; `; render(<Fancy />); -
When you want to keep the styles but change only the element Using withComponent, you can carry over the styles as they are while changing only the element. You can also change the element using the as property.
import styled from '@emotion/styled'; const Section = styled.section` background: #333; color: #fff; `; // this component has the same styles as Section but it renders an aside const Aside = Section.withComponent('aside'); render( <div> <Section>This is a section</Section> <Aside>This is an aside</Aside> </div>, ); import styled from '@emotion/styled'; const Button = styled.button` color: hotpink; `; render( // button -> a tag로 변경 <Button as="a" href="https://github.com/emotion-js/emotion"> Emotion on GitHub </Button>, ); -
When you need to target a component to change its CSS You can change the styles by using @emotion/babel-plugin.
// emotion string styles 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>, ); // emotion 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>, ); -
When you need to forward props conditionally When the shouldForwardProp condition evaluates to true, the prop is not forwarded during rendering.
import isPropValid from '@emotion/is-prop-valid' import styled from '@emotion/styled' const H1 = styled('h1', { // shouldForwardProp 모두 true로 줄 경우 children props로 전달이 안되서 화면이 안보이게 됩니다. / // default as/children 순차적으로 호출됨. shouldForwardProp: prop => isPropValid(prop) && prop !== 'color' })(props => ({ color: props.color })) render(<H1 color="lightgreen">This is lightgreen.</H1>) -
When you need to apply dynamic 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>); -
Nesting components
import styled from '@emotion/styled'; const Example = styled('span')` color: lightgreen; & > strong { color: hotpink; } `; render( <Example> This is <strong>nested</strong>. </Example>, );
-
-
Media Queries
-
Basics
import { css } from '@emotion/react'; render( <p css={css` font-size: 30px; @media (min-width: 420px) { font-size: 50px; } `} > Some text! </p>, ); -
Reusing media queries
import { css } from '@emotion/react'; const breakpoints = [576, 768, 992, 1200]; const mq = breakpoints.map(bp => `@media (min-width: ${bp}px)`); render( <div> <div css={ color: 'green', [mq[0]]: { color: 'gray', }, [mq[1]]: { color: 'hotpink', }, } > Some text! </div> <p css={css` color: green; ${mq[0]} { color: gray; } ${mq[1]} { color: hotpink; } `} > Some other text! </p> </div>, ); -
Using facepaint
- Installation
npm i facepaint or yarn add facepaint
import facepaint from 'facepaint'; const breakpoints = [576, 768, 992, 1200]; const mq = facepaint(breakpoints.map(bp => `@media (min-width: ${bp}px)`)); render( <div css={mq({ color: ['green', 'gray', 'hotpink'], })} > Some text. </div>, ); - Installation
-
-
Global Styles
import { Global, css } from '@emotion/react'; render( <div> <Global styles={css` .some-class { color: hotpink !important; } `} /> <Global styles={ '.some-class': { fontSize: 50, textAlign: 'center', }, } /> <div className="some-class">This is hotpink now!</div> </div>, ); -
Keyframes
import { css, keyframes } from '@emotion/react'; const bounce = keyframes` from, 20%, 53%, 80%, to { transform: translate3d(0,0,0); } 40%, 43% { transform: translate3d(0, -30px, 0); } 70% { transform: translate3d(0, -15px, 0); } 90% { transform: translate3d(0,-4px,0); } `; render( <div css={css` animation: ${bounce} 1s ease infinite; `} > some bouncing text! </div>, ); -
Applying styles globally to a component (spread operator)
import { css } from '@emotion/react'; const pinkInput = css` background-color: pink; `; const RedPasswordInput = props => ( <input type="password" css={css` background-color: red; display: block; `} {...props} /> ); render( <div> <RedPasswordInput placeholder="red" /> <RedPasswordInput placeholder="pink" css={pinkInput} /> </div>, ); -
Applying a theme When wrapped with a ThemeProvider, the theme is shared through the Context API, so it can be used in child components.
// css prop import { ThemeProvider } from '@emotion/react'; const theme = { colors: { primary: 'hotpink', }, }; render( <ThemeProvider theme={theme}> <div css={theme => ({ color: theme.colors.primary })}> some other text </div> </ThemeProvider>, ); // styled import { ThemeProvider } from '@emotion/react'; import styled from '@emotion/styled'; const theme = { colors: { primary: 'hotpink', }, }; const SomeText = styled.div` color: ${props => props.theme.colors.primary}; `; render( <ThemeProvider theme={theme}> <SomeText>some text</SomeText> </ThemeProvider>, ); // useTheme hook import { ThemeProvider, useTheme } from '@emotion/react'; const theme = { colors: { primary: 'hotpink', }, }; function SomeText(props) { const theme = useTheme(); return <div css={ color: theme.colors.primary } {...props} />; } render( <ThemeProvider theme={theme}> <SomeText>some text</SomeText> </ThemeProvider>, ); -
Exposing the className as a value (using labels)
import { css } from '@emotion/react'; let style = css` color: hotpink; label: some-name; `; let anotherStyle = css({ color: 'lightgreen', label: 'another-name', }); let ShowClassName = ({ className }) => ( <div className={className}>{className}</div> ); render( <div> <ShowClassName css={style} /> <ShowClassName css={anotherStyle} /> </div>, ); -
When you need to use css and cx together (using ClassNames)
import { ClassNames } from '@emotion/react'; // this might be a component from npm that accepts a wrapperClassName prop let SomeComponent = props => ( <div className={props.wrapperClassName}> in the wrapper! <div className={props.className}>{props.children}</div> </div> ); render( <ClassNames> {({ css, cx }) => ( <SomeComponent wrapperClassName={css({ color: 'green' })} className={css` color: hotpink; `} > from children!! </SomeComponent> )} </ClassNames>, ); -
When you need to specify a key value (using CacheProvider)
import { CacheProvider, css } from '@emotion/react'; import createCache from '@emotion/cache'; import { prefixer } from 'stylis'; const customPlugin = () => {}; const myCache = createCache({ key: 'my-prefix-key', stylisPlugins: [ customPlugin, // has to be included manually when customizing `stylisPlugins` if you want // to have vendor prefixes added automatically prefixer, ], }); render( <CacheProvider value={myCache}> <div // class: my-prefix-key-zjik7 css={css` display: flex; `} > <div // class: my-prefix-key-yc3urw css={css` flex: 1; transform: scale(1.1); color: hotpink; `} > Some text </div> </div> </CacheProvider>, );
Using the Babel Plugin
-
Installation
npm i -D @emotion/babel-plugin or yarn add -D @emotion/babel-plugin -
.babelrc
{ "plugins": ["@emotion"] } // when you need separate settings per env environment { "env": { "production": { "plugins": ["@emotion", ...otherBabelPlugins] } }, "plugins": ["@emotion"] }
Browser Support
- emotion supports most browsers, including IE11.