Emotion 사용법

이수빈·2023년 9월 1일
1

Next.js

목록 보기
4/15
post-thumbnail
  • Emotion은 Styled-components와 함께 가장 대중적으로 사용되는 CSS-in-JS 방식의 Styling 라이브러리이다.

  • Next.js + TS환경에서 Emotion을 적용했다.

설치 및 babel, tsConfig설정

  • 설치

npm i @emotion/react // React 환경에서 설치
npm i @emotion/styled @emotion/react // styled 컴포넌트 형태로 사용가능

  • babel-plugin 설치 => emotion에서 minification and optimization 기능 제공함.

npm install --save-dev @emotion/babel-plugin

  • .babelrc 파일 설정
{
  "presets": [
    [
      "next/babel",
      {
        "preset-react": {
          "runtime": "automatic",
          "importSource": "@emotion/react"
        }
      }
    ]
  ],
  "plugins": ["@emotion"]
}
  • tsconfig 설정 => emotion/react는 설정필요, emotion/styled는 설정불필요
"jsx": "react-jsx",
"jsxImportSource": "@emotion/react"

사용방법

기본스타일링

  • 2가지 css prop 형식과 styled component형식 혼용가능함 => - 코드 재사용, 컴포넌트 재사용 여부에 따라 사용하면 됨.

  • css() 함수에 넣을때 문자열 or 객체형식으로 넣을 수 있는데, 객체형식이 권장됨.

  • css() 함수를 호출을 생략하고 css prop에 바로 객체를 넘길 수 있으며, 특히 타입스크립트(TypeScript)를 사용하면 타입 체킹(type checking)을 통해 버그도 줄일 수 있기 때문.

const titleStyle = css({
  backgroundColor: "yellow",
  fontSize: "30px",
  "& .namefsd": {
    border: "10px solid black",
    maringTop: "100px",
  },
  "& > div": {
    border: "10px solid black",
    maringTop: "100px",
    backgroundColor: "crimson",
  },
});

Composition

  • css객체의 재사용가능 (코드중복 방지)
import { css } from '@emotion/react'

const hotpink = css({
  color: 'hotpink'
})

const hotpinkHoverOrFocus = css({
  '&:hover,&:focus': hotpink
})

const hotpinkWithBlackBackground = css(
  {
    backgroundColor: 'black',
    color: 'green'
  },
  hotpink
)

/// 이런식으로도 사용가능

const buttonStyle = css({
  border: "10px solid black",
  maringTop: "100px",
  backgroundColor: "crimson",
});

const titleStyle = css({
  backgroundColor: "yellow",
  fontSize: "30px",
  "& > div": buttonStyle,
});

Nested Selector

  • 인접해있는 태그들을 모두 선택가능

const titleStyle = css({
  fontSize: "30px",
  "& > div": buttonStyle, // titleStyle아래 div자식태그들 모두 선택
  button: {
    backgroundColor: "green",
    width: 100,
  }, // titleStyle아래 div태그 선택

  "div &": {
    backgroundColor: "blue",
    height: 1000,
  }, // titleStyle 부모요소중 가장 가까운 div태그 선택
  
   "#contain &": {
    backgroundColor: "black",
  },
});

Global Style 사용가능.

  • Global 컴포넌트 사용가능, 여기 styles 속성에 전역 스타일을 정의해주면 됨

  • Global은 컴포넌트는 children을 가질 수 없음, global.style.ts처럼 파일을 정의해줘야함.


//_app.tsx

import globalStyle from "@/styles/global.style";


function App({ Component, pageProps }: AppProps) {
  return (
    <Provider>
      <Global styles={globalStyle} />
      <Layout>
        <Component {...pageProps} />
      </Layout>
    </Provider>
  );
}

export default App;


//global.style.ts
import { css } from "@emotion/react";

const globalStyle = css`
  html,
  body {
    padding: 0;
    margin: 0;

    overflow-y: auto;
    background-color: pink;
  }

  a {
    color: inherit;
    text-decoration: none;
  }

  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
`;

export default globalStyle;

자주 사용하는 스타일 변수화

  • 문자열 방식이던, 객체로 사용하는 방식이던 자주 사용하는 것들을 js 객체에서 뽑아낼 수 있음.

  • 아니면 객체형식에서 style을 정의해놓을수도 있음

const cardCss = {
  self: css({
    backgroundColor: 'white',
    border: '1px solid #eee',
    borderRadius: '0.5rem',
    padding: '1rem'
  }),

  title: css({
    fontSize: '1.25rem'
  })
}

export const colors = {
  primary: '#0d6efd',
  success: '#198754',
  danger: '#dc3545'
}

동적스타일링

  • style prop을 사용해서 동적스타일링을 정의 할 수 있다.

  • style prop이란? React 컴포넌트에 동적으로 스타일을 적용하기 위한 prop입니다.

  • 이 prop을 사용하면 JavaScript 객체로 정의된 스타일을 컴포넌트에 적용할 수 있습니다. Emotion은 이 스타일 객체를 CSS-in-JS 스타일로 컴파일하고 컴포넌트의 HTML 요소에 스타일을 적용합니다.

  • JS 코드를 통해 동적으로 스타일링을 적용가능함. (객체형태로 style을 적용하는 방식임.


function generateDynamicStyles(dynamicColor : string) {
  return {
    backgroundColor: dynamicColor,
    padding: "10px",
    color: "white",
  };
} // prop을 받아서 동적으로 스타일을 만들어냄
export default function TodoList({color}) {

  const dynamicStyle = generateDynamicStyles(color);
  
  
  return (
  ...
    <div style={dynamicStyle}>test</div>
  ...
 )

}

가변스타일링

  • 객체의 key로 변수처럼 사용가능함 => 내부 style에서 처리하게 하지 않으려면?
/** @jsxImportSource @emotion/react */

const fontSize = {
  small: "14px",
  medium: "16px",
  large: "18px",
};

function Button({ children, variant = "medium" }) {
  return (
    <button
      css={{
        borderRadius: "6px",
        fontSize: fontSize[variant],
      }}
    >
      {children}
    </button>
  );
}

export default Button;

ref) 공식문서 : https://emotion.sh/docs/object-styles

profile
응애 나 애기 개발자

0개의 댓글