.js
파일에 css
를 넣을 수 있도록 해주는 편리한 라이브러리
(CSS-in-JS 라이브러리 라고 부른다고 함)
yarn add styled-components
로 다운받을 수 있음
import styled from 'styled-components';
다음처럼 .js
파일에서 import
const variable = styled.div``;
사용법은 위와 같음. 변수 안에 집어넣는데, .div
부분은 .input
, .button
등등으로 바꿀 수 있음
그리고 안에는 css
코드를 삽입
const variable = styled.div`
width: 100px;
height: 100px;
background: red;
border-radius: 4px;
`;
보통 css
처럼 사용하면 되는데, 이를 렌더링 할때도 <variable>
태그를 써서, 안에 내용물들을 넣어 줄 수 있음
즉, 원래는 <div className="variable"/>
이런식으로 정의하고 다른 .css
나 .scss
같은 파일에서 그걸 꾸미는 코드를 넣어줘야 하는데, 그럴 필요없이 .js
파일로만 해당 div
를 꾸며줄 수 있다는 얘기
우리가 알고 있는
`hihihi ${name}`
이런 류는 템플릿 리터럴 이라고 부르긴 하지만, 앞에 tagged
라는게 들어가지 않는다.
템플릿 리터럴은 그냥 문자열 안에 특정 자바스크립트 값을 넣어 문자열을 만드는 것 (백틱'`'을 사용)
일반 템플릿 리터럴의 경우는 문제가 객체나, 함수를 출력하려고 할때인데, 객체의 경우는 단순히 [Object]
이런식으로 출력이 되고, 함수는 함수의 내용물이 그냥 출력된다 예를 들어
const hi = () => {}
라는 함수를 ${hi}
로 출력해보면, () => {}
가 출력된다.
반면 Tagged Template Literal
은 다음과 같이 쓸 수 있다.
const coffee = '카페라떼'
const price = '3000'
function favoriteCoffee(texts, ...values){
console.log(texts);
console.log(values);
}
favoriteCoffee`제가 제일 좋아하는 커피는 ${coffee}이고, 가격은 ${price}입니다.`;
실제로 출력해보면 위와 같은데, 한마디로, ()로 함수를 호출하는게 아니라 ``로 호출하는데 그 안의 내용물들이 매개변수처럼 보이지만, 값이 두 분류로 토막나는 과정이 더해진 다음 함수 호출이 이뤄진다. 문자열과 ${}를 사용한게 각각 따로 호출된다.
이걸 잘 활용해보면 ``로 함수를 호출할때 매개변수를 reduce를 통해서 각각의 ${}에 태그를 더 넣어줄 수 있다. 예를 들면 b(bold 태그) 라든가
그럼 styled-components
에선 이걸 어떻게 쓸까?
const variable = styled.div`
width: 100px;
height: 100px;
background: red;
border-radius: 4px;
`;
위 처럼, 단순히 외부의 값을 아무것도 읽지 않는 경우라면 모르겠지만, 호출하는 쪽에서
<variable color="white"></variable>
같이 props
를 넣어주게 되면, 이를 읽어들일 필요가 있다. 그래서 Tagged Template Literal이 쓰이는 것이다.
아래 추가 설명
const Text = styled.div`
flex: 1;
font-size: 21px;
color: #495057;
${props =>
props.done &&
css`
color: #ced4da;
`};
`;
다음 코드에서는 못 보던 코드가 생겨서 조금 당황스러운 것이 있음
바로 ${props}
하지만 해석은 실로 단순함
<Text done={done}>{text}</Text>
건네주는 쪽의 코드가 위와 같은데, 보면 done={done}
으로 props
를 넘겨주고 있음
styled-components
에서는 props
를 ${props}
로 받고, 안의 내용물들을 사용하고 싶으면 위의 경우처럼 ${props => props.something}
이런식으로 사용하면 됨 => 이것이 바로 Tagged Template Literal 사용 이유
어떻게 사용할 수 있는 거냐 궁금한데, 예시를 가져와 보겠다.
function example(texts, ...fns){
const props = {
title: '어렵다.',
body: '어려워용'
}
return texts.reduce((result, text, i) => `$(result)${text}${fns[i] ? fns[i](props) : ''}`, '');
}
//호출 쪽
example`
title!: ${props => props.title}
content!: ${props => props.body}
`
/*결과
title!: 어렵다.
content!: 어려워용
*/
이번엔 TTL(태그 리터럴 템플릿을 그냥 줄여서 이렇게 부르겠다 네트워크에서의 Time To Live 아님..)에 함수를 넣어서 호출을 하는 모습을 볼 수 있는데, 함수에선 이 함수를 매개변수로 받아 ...fns로 만들어준다.
그리고 reduce함수를 통해 그 값을 조작할 수가 있는데, props에 있는 걸 fns의 파라미터로 넣어서 결과물을 만들어낸다.
따라서 Styled-Components에서 props를 받아들여오면 그걸 이용해서 어떤 원리를 통해 CSS코드를 실행시키는 것이다.
아까 보던 코드를 다시 봐보자.
```javascript
const Text = styled.div`
flex: 1;
font-size: 21px;
color: #495057;
${props =>
props.done &&
css` // => 이건 뭐지..?
color: #ced4da;
`};
`;
독특한 코드가 있는데 바로 css``이다.
이 코드는 ${}
안에서도 TTL코드를 적어서 적용할 수 있도록 해준다. 만약 css를 적지 않는다면, TTL이 아니라 그냥 템플릿 리터럴이 된다. 즉 ``안에는 ${}를 적어도 styled에게 TTL처럼 전달이 되지 않는다.
${props =>
props.done &&
css`
color: #ced4da;
`};
이 코드의 경우 props
에서 가져온 done
이 true
이면 뒤의 css
코드에 의해서 text의 색상이 #ced4da
로 바뀜 하지만 만약 done
이 false
라면 색은 기본값인 #495057
다.
이 css
를 사용하려면,
import { css } from styled-components;
가 필요하다.
자세한 설명은
https://styled-components.com/docs/api#css
를 참고하자.
styled-components안에서 sass
에서 사용하는 darken, lighten
같은 기능들을 사용할 수 있도록 해주는 라이브러리
yarn add polished
로 가져오고 styled-components의 TTL 태그안에서는
${lighten(0.1, '색깔')}
이런식으로 쓸 수 있다.
App.js에서 {ThemeProvider}
를 import하면, App의 자식 컴포넌트들도 App에서 선언한 Theme를 가져다 사용할 수 있다. 즉 색상들을 ThemeProvider를 통해 제공하고 자식 컴포넌트들은 굳이 자신의 파일안에 선언하지 않아도 부모 컴포넌트에서 제공하는 색상들을 쓸 수 있다.
const palette = {
blue: '#228be6',
lime: '#d8f5a2',
pink: '#f06595',
};
다음과 같이 정의된 색상을
<ThemeProvider theme={{ palette }}>
<AppBlock>
<div className="buttons">
<Button>BUTTON</Button>
<Button color="pink">BUTTON</Button>
<Button color="lime">BUTTON</Button>
</div>
</AppBlock>
</ThemeProvider>
이런식으로 ThemeProvider태그의 theme prop을 통해 설정해두면,
${({ theme, color }) => {
const selected = theme.palette[color];
return css`
background: ${selected};
&:hover {
background: ${lighten(0.1, selected)};
}
&:active {
background: ${darken(0.1, selected)};
}
`;
}}
//호출 부
<StyledButton color={color} {...rest}>
{children}
</StyledButton>
Button.js에서도 비구조화 할당을 통해, 컴포넌트 태그에서 건네준 color와, App.js에서의 theme를 받아 사용할 수 있다.
전역적으로 무언가를 적용하고 싶을때 사용 예를 들면 background
const GlobalStyle = createGlobalStyle`
body{
background: #e9ecef;
}
`;
function App() {
return (
<~~~~>
<GlobalStyle />
<~~~>
<~~~ />
<~~~ />
<~~~ />
</~~~>
</~~~>
);
}
App.js
에서 다음같이 파일을 만들어주고, 위 코드 처럼, 가장 밖에서 감싸고 있는 태그 안에 적어주기만 하면 배경색이 #e9ecef
가 됨