css-in-js는 2018년 이후 폭발적으로 성장해 왔다. 그 중 Styled-Components는 npm 다운로드 수 기준으로 현재 가장 인기 있는 css-in-js 라이브러리이다.
공식 문서
https://styled-components.com/
styled-components 라이브러리에서 import 해온 styled라는 객체를 이용한다.
아래와 같이 h1 태그를 만들어 Title이라는 Styled-Components를 만들 수 있다.
import styled from 'styled-components'
render(
<Wrapper>
<Title>
스타일 컴포넌트를 사용해보자!
</Title>
</Wrapper>
);
const Wrapper = styled.section`
padding: 4em;
background: yellowgreen;
`;
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
styled-components 에서는 스타일을 입력 할 때 Tagged 템플릿 리터럴(Template Literal) 이라는 ES6 문법을 사용한다. 이 문법을 사용하는 이유는, `` 를 사용할 때 내부에 JavaScript 객체나 함수가 전달 될 때 이를 따로 추출하기 위함이다.
정말 정말 유용한 기능이다!!
스타일 컴포넌트 답게 props를 사용하여 재사용 할 수가 있다.
이를 이용하여 편리하게 동적인 스타일을 지정 할 수 있다.
render(
<div>
<Button>Normal</Button>
<Button primary width="100">Primary</Button>
</div>
);
// 만약 Button 컴포넌트에 전달된 props(width)가 200 미만(조건)이면
// 삼항연산자 true : "blue"
// 삼항연산자 false : "white"
const Button = styled.button`
background: ${props => props.width < 200 ? "blue" : "white"};
color: ${props => props.primary ? "white" : "blue"};
font-size: 1em;
margin: 20px;
padding: 10px 8px;
border: 2px solid blue;
border-radius: 3px;
`;
Styled Components 역시 해당 기능을 제공한다.
적절히 사용한다면 모든 컴포넌트를 스타일드 컴포넌트화 시키지 않더라도 충분히 스타일링할 수 있다.
<Garrery>
<h2>무비 갤러리</h2>
<div>
{
data.map( item => <article key={item.no}>
<img src={item.poster} alt="" />
<h3> {item.title} </h3>
<p> { item.director } </p>
</article>)
}
</div>
</Garrery>
const Garrery = styled.div`
div {
display:flex;
article{
display:flex-item;
margin-right:15px;
width:300px;
img { width:100% ; transition:0.4s; }
:hover {
img {
opacity:0.7
}
}
}
}
`
다른 스타일링을 상속하는 새 구성 요소를 쉽게 만들려면 아래 예시와 같이 styled(변수)를 적용해주면 된다.
render(
<div>
<Button>Normal Button</Button>
<TomatoAnchorButton>Tomato Button</TomatoAnchorButton>
</div>
);
const Button = styled.div`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
const TomatoAnchorButton = styled(Button.withComponent("a"))`
color: tomato;
border-color: tomato;
`;
createGlobalStyle 과 ThemeProvider을 사용하여 전역으로 사용할 스타일링을 정의 할 수 있다.
// GlobalStyles.js
import { createGlobalStyle } from 'styled-components';
import reset from 'styled-reset';
const GlobalStyles = createGlobalStyle`
${reset};
*{
margin:0;
padding:0;
box-sizing:border-box;
}
body{
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR&display=swap');
font-family: 'Noto Sans KR', sans-serif;
background-color: white;
}
`;
export default GlobalStyles;
// theme.js
import { css } from 'styled-components';
const theme = {
fontPointColor: '#FF7B5C',
};
export default theme;
// index.js
ReactDOM.render(
<>
<GlobalStyles />
<ThemeProvider theme={theme}>
<Routes />
</ThemeProvider>
</>,
document.getElementById('root'),
);
import { css } from "styled-components"
const Navigation = styled.nav`
position: fixed;
left: 0;
top: 0;
right: 0;
${Sticky}
`;
const flexColumnAlign = css`
display: flex;
flex-direction: column;
align-items: center;
`;