Emotion 더 잘 사용하기!

boyeonJ·2023년 12월 29일
0

HTML/CSS

목록 보기
13/13

📌 이 글은 emotion 공식문서의 Best Practices 참고하여 작성되었습니다.

스타일 재사용 하기

어떤 애플리케이션을 개발하는데 에러메세지 스타일이 여러 컴포넌트에서 반복적으로 사용되며, 해당 에러메세지는 폰트사이즈가 다른 여러버전이 존재한다고 가정해봅시다.

이러한 스타일을 재사용하기 위해 스타일을 공유하는 방법은 두가지가 있습니다.

1. css objects를 export 해주기

export const errorCss = css({
  color: 'red',
  fontWeight: 'bold'
})

// Use arrays to compose styles
export const largeErrorCss = css([errorCss, { fontSize: '3rem' }])
export const mediumErrorCss = css([errorCss, { fontSize: '2rem' }])
export const smallErrorCss = css([errorCss, { fontSize: '0.5rem' }])
import { errorCss, largeErrorCss, mediumErrorCss , smallErrorCss} from '...'

return (
	<p css=[errorCss, {fontSize: '5rem'}]>Failed!!!!!!!</p>
	<p css={largeErrorCss}>Failed!!!</p>
	<p css={mediumErrorCss}>Failed!!</p>
	<p css={smallErrorCss}>Failed!</p>
)

2. 컴포넌트 재사용 해주기

아래처럼 컴포넌트 자체를 재사용 해줄 경우 좀 더 반복적이 코드를 줄일 수 있습니다.

export function ErrorMessage({ className, children }) {
  return (
    <p css={{ color: 'red', fontWeight: 'bold' }} className={className}>
      {children}
    </p>
  )
}

export function LargeErrorMessage({ className, children }) {
  return (
    <ErrorMessage css={{ fontSize: '3rem' }} className={className}>
      {children}
    </ErrorMessage>
  )
}

📌 css={}로 넘긴 css object는 하위컴포넌트의 className으로 넘어감

import { ErrorMessage, LargeErrorMessage} from '...'

return (
	<ErrorMessage css={{ fontSize: '5rem' }}>Failed!!!!!!!</ErrorMessage>
	<LargeErrorMessage>Failed!!!</LargeErrorMessage>

동적으로 스타일 주기

만약 다른 스타일은 동일하지만 backgroud-style만 달라지는 경우에 어떻게 구현할 수 있을까요?

만약 동적으로 스타일을 줄 수 없다면 아래와 같이 중복되는 코드를 계속해서 작성해야 할 것입니다.

<style>
  .css-1udhswa {
    border-radius: 50%;
    width: 40px;
    height: 40px;
    background-style: url(https://i.pravatar.cc/150?u=0);
  }

  .css-1cpwmbr {
    border-radius: 50%;
    width: 40px;
    height: 40px;
    background-style: url(https://i.pravatar.cc/150?u=1);
  }

  .css-am987o {
    border-radius: 50%;
    width: 40px;
    height: 40px;
    background-style: url(https://i.pravatar.cc/150?u=2);
  }
</style>

이를 style props를 사용한다면 쉽게 해결 할 수 있습니다.
1. style 코드에서는 var(변수명) 형태로 사용
2. element에서는 style={{'변수명' : 값}} 으로 넘겨주면 됩니다.

.avatar {
  border-radius: 50%;
  width: 40px;
  height: 40px;
  background-style: var(--background-style);
}

function Avatar({ imageUrl }) {
  return <div className="avatar" style={{ '--background-style': imageUrl }} />
}

만약 typescript를 사용한다면 style={{ ['--background-style' as any]: imageUrl }} 이렇게 사용해주면 된다.

Theming 사용하기

dark mode, light mode를 개발하는 방법중에 emotion의 ThemeProvider을 사용하는 방법이 있습니다.

1. App top level에 ThemeProvider 추가해주기

import { ThemeProvider } from '@emotion/react'

const theme = {
  colors: {
    primary: 'hotpink'
  }
}

render(
  <ThemeProvider theme={theme}>
    <App.js>
  </ThemeProvider>
)

2-1. useTheme 사용하기

import {useTheme } from '@emotion/react'

const theme = {
  colors: {
    primary: 'hotpink'
  }
}

function SomeText(props) {
  const theme = useTheme()
  return <div css={{ color: theme.colors.primary }} {...props} />
}

2-2. css 에서 theme 활용해주기

import {useTheme } from '@emotion/react'

const theme = {
  colors: {
    primary: 'hotpink'
  }
}

function SomeText(props) {
  return <div css={theme => ({ color: theme.colors.primary })}>some other text</div>
}

ThemeProvider는 Context API로 전체 테마를 바꾸는 것입니다. 그런데 이는 CSS 변수 접근 방식과 비교하면 아래의 두가지 단점이 존재합니다.
1. DX 하락: 코드가 복잡해짐
2. 성능 하락: ThemeProvider 접근 방식을 사용하면 모든 구성 요소의 스타일을 업데이트해야 하며 브라우저는 해당 업데이트를 페인트함, 그러나 CSS 변수 접근 방식을 사용하면 스타일을 단일 구성 요소(본문)로 업데이트한 다음 브라우저에서 해당 업데이트를 페인트함

참고

0개의 댓글