styled-components는 CSS-in-JS 라이브러리로 Tagged Template Literals이라는 ES6 문법을 사용하여 스타일을 지정합니다. HTML 엘리먼트나 React 컴포넌트를 전달하고 백틱(`) 기호 내에 CSS 코드를 작성하면 스타일이 적용된 HTML 엘리먼트나 React 컴포넌트를 반환합니다.
template literals 의 더욱 발전된 한 형태는 tagged templates 입니다. 태그를 사용하면 템플릿 리터럴을 함수로 파싱 할 수 있습니다. 태그 함수의 첫 번째 인수는 문자열 값의 배열을 포함합니다. 나머지 인수는 표현식과 관련됩니다.
styled.h1`` 문법은 h1 이라는 함수를 호출하는 것(styled.h1())과 같습니다. 하지만 차이점은 tagged templates literals를 사용하면 템플릿 리터럴이 모두 분할되어 문자열 배열을 첫 번째 인자로 가지고 다음 인자는 스트링 템플릿(${}
)으로 전달된 값들을 갖습니다.
const logArgs = (...args) => console.log(...args)
const favoriteFood = 'pizza'
logArgs(`I like ${favoriteFood}`)
// I like pizza
logArgs`I like ${favoriteFood}`
// ['I like ', ''] 'pizza'
이를 사용한 styled-components에서의 예제로 살펴보겠습니다.
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
`;
const App = () => {
console.log(Title);
return <Title>ToDoList</Title>
};
전달한 HTML Element에 해시값으로 자동으로 클래스명이 생성되었고 스타일 태그로 적용된 것을 확인할 수 있습니다. 출력 결과의 componentStyle > rules
를 살펴보면 tagged templates literals 문법으로 표현되어 있습니다.
데이터를 가공하는 방법에 대해서는 "Styled Components의 작동 원리 (ES6 태그 템플릿)" 이 영상을 참고해보세요.
styled-components는 렌더링 될 때 DOM 요소에 고유한 클래스명이 주입되므로 다른 요소에 영향을 미치지 않으며 CSS 표준 문법을 사용해 쉽게 스타일을 적용할 수 있게 합니다.
tagged templates literals로 함수가 호출될 때 실제 함수가 전달됩니다. 아래 예제에서 괄호를 사용해 execFunArgs
함수를 호출했을 때 실제 함수가 전달되지 않았기 때문에 아무 일도 일어나지 않습니다. 그저 단순한 문자열이 전달된 것입니다.
const execFuncArgs = (...args) => args.forEach(arg => {
if (typeof arg === 'function') {
arg()
}
})
execFuncArgs(`Hi, ${() => { console.log('Executed!') }}`)
// undefined
execFuncArgs`Hi, ${() => { console.log('Executed!') }}`
// "Executed!"
template literal 문법으로 함수를 전달할 수 있기 때문에 props에 기반한 동적인 스타일링이 가능한 것!
const Button = styled.button`
font-size: 1em;
color: ${props => props.primary ? "white" : "palevioletred"};
`;
return (
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);