본문 바로가기

Frontend

🕶️ emotion.js 공부 하기

 

emotion.js란?

emotion.js는 CSS-in-JS의 종류 중 하나로 JavaScript 안에서 스타일을 작성할 수 있게 해준다.

 

설치

# Framework Agnostic
$ npm install @emotion/css

# React
$ npm install @emotion/react

@emotion/css 패키지는 프레임워크에 구애받지 않으며 Emotion 을 사용할수 있는 방법이다.
바벨 플러그인, config 변경 같은 다른 추가 셋팅이 필요하지 않는다.
자동으로 벤더프리픽스를 지원하고, 중첩 선택자, 미디어 쿼리를 지원한다.
css 클래스 이름을 생성하고 cx 구성하는 기능을 사용하는 것을 선호한다.

 

import

emotion.js를 사용해야 할 컴포넌트에 import 해야 한다.

/** @jsx jsx */
import { jsx, css } from '@emotion/react'

 

css props

이모션으로 요소를 style 링 하는 주된 방법은 css props 를 사용하는 것이다.

 

 

JSX Pragma

jsx pragma 를 css props 을 사용하는 소스 파일의 가장 상단에 둬야한다.
이 option 은 css prop 기능을 테스트 하거나 babel 구성을 구성할 수 없는 프로젝트(create-react-app, codesandbox 등)에서 가장 잘 작동한다.

React v16 이하의 버전을 사용하는 곳에서는 아래와 같이 써야하고, jsx() 함수도 불러와야한다.

/** @jsx jsx */
import {css, jsx} from '@emotion/react";

 

이것은 React.createElement 대신 jsx 함수를 사용하도록 jsx babel 플러그인을 구성하는 것이다.

그 이상의 버전에서는

 /** @jsxImportSource @emotion/react */

 

위와 같이 상단에 쓰면, React 의 jsx() g함수를 사용하지 말고 Emotion 의 jsx() 함수를 사용하라는 뜻이다.

써주지 않으면 css prop 에 넘어간 스타일이 제대로 반영이 안될 수 있다.

 

스타일 우선순위

className 속성의 이모션 스타일을 포함하는 className 이 css 속성 스타일을 재정의한다.
이모션 외의 소스에서 가져온 클래스 이름은 무시되고 계산된 이모션 클래스 이름에 추가된다.

우선순위 순서는 직관적이지 않은 것처럼 보일 수 있지만, 부모로 부터 전달된 className prop 을 통해 css prop에 정의된 스타일을 가진 구성 요소를 커스텀 할 수 있다.

const P = props => (
  <p
    css={{
      margin: 0,
      fontSize: 12,
      lineHeight: '1.5',
      fontFamily: 'Sans-Serif',
      color: 'black'
    }}
    {...props} // <- props contains the `className` prop
  />
)

const ArticleText = props => (
  <P
    css={{
      fontSize: 14,
      fontFamily: 'Georgia, serif',
      color: 'darkgray'
    }}
    {...props} // <- props contains the `className` prop
  />
)

위 예제의 경우 p 요소의 css 가 정의되어 있는데, ArticleText 요소가 p를 재정의 함으로써

중복된 css 가 덮어 씌워진다.
fontSize, fontFamily, color 는 ArticleText 에 정의된 것이 우선한다.

 

 

Composition

Composition 은 이모션에서 가장 강력하고 유용한 기능이다. CSS에서 반환된 값을 다른 스타일 블록에 보간하여 스타일을 함께 구성할 수 있다.

import { css } from '@emotion/react'

const base = css`
  color: hotpink;
`

render(
  <div
    css={css`
      ${base};
      background-color: #eee;
    `}
  >
    This is hotpink.
  </div>
)

 

일반적으로 css 는 여러 클래스를 사용하여 스타일을 함께 구성할 수 있지만, 정의된 순서에 따라 나중에 정의된 것이 우선된다.

그런데 Emotion 을 사용하면 스타일을 만들고 결합할 수 있다.
이모션의 Compositon 을 사용하면 스타일이 사용 순서대로 병합되므로 스타일이 생성된 순서를 생각할 필요가 없다.

import { css } from '@emotion/react'

const danger = css`
  color: red;
`

const base = css`
  background-color: yellow;
  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>
)

중첩 선택자

import { css } from '@emotion/react'

const paragraph = css`
  color: turquoise;

  a {
    border-bottom: 1px solid currentColor;
    cursor: pointer;
  }
`
render(
  <p css={paragraph}>
    Some text. <a>A link with a bottom border.</a>
  </p>
)

paragraph 안의 a 태그에 대한 style 은 위와 같이 줄 수 있다.

또한 & 를 사용해서 다른요소에 중첩된 현재 클래스를 선택할 수 있다.

import { css } from '@emotion/react'

const paragraph = css`
  color: turquoise;

  header & {
    color: green;
  }
`
render(
  <div>
    <header>
      <p css={paragraph}>This is green since it's inside a header</p>
    </header>
    <p css={paragraph}>This is turquoise since it's not inside a header.</p>
  </div>
)

paragraph 중 header 에 중첩된 요소는 color 가 green 으로 표시된다.

'Frontend' 카테고리의 다른 글

🕶️ TypeScript 공부 하기 3장  (0) 2023.07.14
🕶️ recoil 공부 하기  (0) 2023.07.13
🕶️ TypeScript 공부 하기 2-2장  (0) 2023.07.11
🕶️ TypeScript 공부 하기 2-1장  (1) 2023.07.10
🕶️ TypeScript 공부 하기 1장  (0) 2023.07.05