Styled-Components

Styled-Components란

React에서 사용되는 CSS-in-JS 라이브러리

Install

npm i styled-components
npm i -D @types/styled-components @swc/plugin-styled-components

.swcrc

Babel Plugin을 SWC에서 쓸 수 있도록 포팅한 것도 함께 설치하자(SSR 지원 등을 위한 공식 권장사항).

{
  "jsc": {
    "experimental": {
      "plugins": [
        [
          "@swc/plugin-styled-components",
          {
            "displayName": true,
            "ssr": true
          }
        ]
      ]
    }
  }
}

Usage

HTML 요소 이름을 추가한 다음 백틱(`) 기호로 감싼 영역에 CSS 코드를 작성하면 CSS 스타일이 반영된 React 컴포넌트를 만들어낸다.

import styeld from 'styled-components'

const StyledH2 = styled.h2`
  color: #0066ff;
  font-size: 1.5rem;
`

동작 원리

백틱을 이용한 Tagged Template literals 문법을 사용하여 스타일을 생성한다.

Tagged Template Literals 문법이란?

Template Literals(`) 과 함께 사용되는 함수로, 함수 앞에 백틱을 이용해 문자열과 ${}로 감싼 js 코드를 작성하면 해당 함수의 인자로 전달되어 호출된다.

  • 첫 번째 인자로 ``(백틱)으로 묶인 문자 값의 배열이 전달된다.

  • 두 번째 인자부터는 ${}(템플릿 스트링)으로 감싼 JS 표현식의 결과 값이 사용한 순서대로 전달된다.

const result = styledTag`
 태그
 ${1 + 9}
 템플릿
 ${'불타는' + '청춘'}
 리터럴
 ${ true && 'return True'}
`

const styledTag = (strings, ...expressions) => {
  console.log(strings);
  // ["  태그  ","  템플릿  ","  리터럴  "]
  
  console.log(expressions);
  // "[10, '불타는 청춘', 'return True']  
}

아래 코드는 실제로 스타일드 컴포넌트의 내부 동작 코드가 아니고, 태그드 리터럴 템플릿을 어떻게 사용하는지에 대한 예시 코드이다.

스타일드 컴포넌트는 태그드 탬플릿 리터럴을 사용해서 스타일이 포함된 컴포넌트 객체를 만들고 렌더링 될 때 컴포넌트에 동적으로 생성된 클래스를 부여하고 해당 스타일을 <style> 태그에 추가한다.

styleTag('h1')`
  color: #0066ff;
  background: #fff;
`
// 위 아래는 같음
styleTag('h1')([
  color: #0066ff;
  background: #fff;
})

function styleTag(element) {
  const styleEl = document.createElement(element)
  
  return function(cssText) { // 함수를 반환하는 고차함수
    const cssStyles = cssText.toString().split(';');
    const cssKeyValues = cssStyles.map(style => style.trim().split(':');               cssKeyValues.forEach([key, value]) => {
      if (key && value) {
        styleEl.style[key] = value;
      }
    }
    return styleEl
  }
}

컴포넌트 커스텀

  • 컴포넌트를 커스텀하는 것도 가능하다.

  • styled가 동적으로 클래스를 생성하기 떄문에 이 커스텀 클래스를 커스텀할 컴포넌트와 연결 해주어야 한다.

  • 커스텀하는 컴포넌트는 className props를 추가하고 커스텀 할 요소에 지정해주어야 한다. (보통은 가장 바깥에 걸어둠)

const Button = styled(Component)`
  //...
`;

export defaulft Componet(className) {
  return <StyledComponent className={className} />
}

props

조건부 스타일을 지정할 때 활용

import styled, { css } from 'styled-components';

type ParagraphProps = {
  active?: boolean;
}

const Paragraph = styled.p<ParagraphProps>`
  color: ${(props) => (props.active ? '#F00' : '#888')};
  ${(props) => props.active && css`
    font-weight: bold;
  `}
`;

// 동일

const Paragraph = styled.p<ParagraphProps>`
  ${({ active }) => css`
    color: ${active ? '#f00' : '#888'}; 
    font-weight: ${active ? 'bold' : 'normal'
  `}
`;

스타일드 컴포넌트에 추가 속성을 지정할 수 있는 props

기본 속성을 추가할 수 있음. 불필요하게 반복되는 속성을 처리할 때 유용한데, 버튼 등을 만들 때 적극 활용함.

import styled from 'styled-components';

export const Button = styled.button.attrs({
  type: 'button',
})`
  border: 1px solid #888;
  background: transparent;
  cursor: pointer;
`;

Last updated