리액트 프레임워크 사용 X
-
설치
npm i @emotion/css or yarn add @emotion/css
-
설명
- 추가적인 setup, babel plugin, 다른 환경설정이 요구하지 않는다.
- auto vendor-prefixing, nested selectors, 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
- css 함수 사용 시 classname 자동생성, cx도 포함해서 class 여러개를 통합까지 지원한다.
- 단, 서버사이드 랜더링 시 추가적인 작업이 요청된다.(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>, );
리액트 프레임워크 사용 O
-
@emotion/react
-
설치
npm i @emotion/react or yarn add @emotion/react
-
설명
- css prop 지원
- auto vendor-prefixing, nested selectors, 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
- 컴포너트 합성/스타일 지정 시 보일러플레이트 코드를 줄일 수 있다.
- auto vendor-prefixing, nested selectors, media queries 지원한다..
- 서버 사이드 렌더링 수행 시 따로 환경세팅 필요없다.
- proper pattern 과 환경구성을 적절하게 이용을 위해서는 ESLint 사용을 제안합니다.
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>, );
- css prop 지원
-
-
@emotion/styled
-
설치
npm i @emotion/styled @emotion/react or yarn add @emotion/styled @emotion/react
-
설명 컴포넌트 생성 시 styled.div와 같은 스타일을 선호하는 사용자를 위한 패키지 입니다.
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 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 스타일링
import styled from '@emotion/styled'; const Basic = ({ className }) => <div className={className}>Some text</div>; const Fancy = styled(Basic)` color: hotpink; `; render(<Fancy />);
-
스타일은 그대로 적용하면서 엘리먼트만 변경할 경우 withComponent를 활용해서 스타일은 그대로 가져오면서 엘리먼트만 변경이 가능하다. 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>, );
-
컴포넌트를 타겟팅해서 CSS 변경해야할 경우 @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>, );
-
조건에 따른 props 전달해야할 경우 shouldForwardProp 조건으로 true 일경우 렌더링 시 props를 전달하지 않는다.
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>)
-
동적 스타일 적용해야할 경우
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
-
기본
import { css } from '@emotion/react'; render( <p css={css` font-size: 30px; @media (min-width: 420px) { font-size: 50px; } `} > Some text! </p>, );
-
미디어쿼리 재사용
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>, );
-
facepaint 사용
- 설치
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>, );
- 설치
-
-
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>, );
-
컴포넌트 스타일에 대한 전체적용(spread 연산)
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>, );
-
테마 적용 ThemeProvider로 감싼경우 contextapi로 공유가 되기 때문에 자식컴포넌트에서 사용이 가능하다.
// 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>, );
-
className을 값으로 보여줄 경우(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>, );
-
css, cx를 동시에 사용해야할 경우(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>, );
-
key값을 지정해야할 경우(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>, );
Babel Plugin 사용
-
설치
npm i -D @emotion/babel-plugin or yarn add -D @emotion/babel-plugin
-
.babelrc
{ "plugins": ["@emotion"] } // env 환경에 따라서 각각 세팅을 해야할 경우 { "env": { "production": { "plugins": ["@emotion", ...otherBabelPlugins] } }, "plugins": ["@emotion"] }
브라우저 지원범위
- emotion은 IE11 포함한 대부분의 브라우저를 지원합니다.