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