기존의 CSS를 구현하는 방식은 .css 파일을 따로 만들어서 css selector를 이용하여 element들을 선택하여 스타일을 지정해주는 방식으로 구현하는 것이다.
👉 이러한 방식의 단점은 className을 잘 지정해주어야 하고, className이 많아지고 중복이 되면 유지보수에 어려움을 겪을 수 있다.
물론 CSS 방법론에 따라 능숙하게 구현 하는 분들은 제외한다.....
CSS모델을 문서 레벨이 아니라 컴포넌트 레벨로 추상화한다.
쉽게 말해 CSS 스타일링을 따로 .css 파일을 만들어 관리하는 것이 아니라, JS 파일에서 스타일링을 하며 컴포넌트 방식으로 사용한다는 것이다.
👉 필자는 보편적인 CSS 사용법을 고수해왔으며 CSS-in-JS의 필요성을 별로 느끼지 못했었다. 하지만 리액트를 이용하여 개발하게 되면서, 컴포넌트를 이용한 구현을 많이 하게되고, 재사용성을 늘리려하다 보니 자연스럽게 CSS-in-JS 방식에 눈이 갔다.
직접 경험해본 결과 CSS-in-JS를 사용하면 CSS를 수정하려고 할 때, 파일을 이리저리 이동하면서 className을 확인하면서 바쁘게 수정할 필요가 없다.
그리고 가장 중요한 것은 CSS를 그대로 옮길 수 있다는 것이다..
컴포넌트를 재사용할 때, CSS 내용을 옮기는 것이 조금 번거로웠다. 왜냐하면 CSS 코드는 전역적이기 때문에 중복되는 부분이 많았다..
npm install --save styled-components
import styled from 'styled-components';
const Container = styled.div `
height:100vh;
width:100%;
background:blue;
& > .hello {
color:red;
}
`
Container라는 styled-component를 만들었다. styled.(태그)
를 이용하여 컴포넌트를 만드는데, 위와 같이 div를 꾸며줄 컴포넌트는 styled.div
, input 태그를 꾸며줄 컴포넌트는 styled.input
등 이런식으로 만들면 된다.
문법은 기본적으로 CSS
문법을 사용할 수 있고, SASS(SCSS)
문법 또한 사용 가능하다.
import styled from 'styled-components';
import React from 'react';
const Container = styled.div`
height:100vh;
width:100%;
background:blue;
& > .hello {
color:red;
}
`
const Button = styled.button`
border-radius: 50px;
padding:5px;
min-width:120px;
color:white;
font-weight: 600;
cursor:pointer;
-webkit-appearance: none;
&:active,
&:focus {
outline:none;
}
`
function App() {
return(
<Container>
<h1 className='hello'>hello</h1>
<Button>success</Button>
<Button>danger</Button>
</Container>
)
}
React 개발에서 컴포넌트를 사용하듯이 사용하면 된다.
& > .hello{
color:red;
}
위의 SCSS 문법을 통해 Container 스타일 컴포넌트 내부에 h1태그의 color를 red로 바꿔주는 것을 볼 수 있다.
body의 margin과 padding을 0으로 만들어보자.
먼저, createGlobalStyle
을 import하고 사용한다.
import styled, { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body{
margin:0;
padding:0;
}
`
(생략)
function App() {
return(
<GlobalStyle/>
<Container>
<h1 classname='hello'>hello</h1>
</Container>
)
}
전역적으로 styled-components를 사용하여 스타일을 구성하고 싶다면 위의 코드처럼 사용하면 된다.
createGlobalStyle을 이용하여 스타일 컴포넌트 만들기
최상위 컴포넌트의 최상위에 GlobalStyle 선언
주의할 점은 감싸는 것이 아니라 최상위에 선언만 해주면 된다.
import styled, { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body{
margin:0;
padding:0;
}
`
const Button = styled.button`
border-radius: 50px;
padding:5px;
min-width:120px;
color:white;
font-weight: 600;
cursor:pointer;
-webkit-appearance: none;
&:active,
&:focus {
outline:none;
}
`
const Anchor = styled(Button)`
text-decoration:none;
color:black;
`
function App() {
return(
<GlobalStyle/>
<Container>
<h1 classname='hello'>hello</h1>
<Button>success</Button>
<Button>danger</Button>
<Anchor as='a' href='https//www.google.com'>
Go to google </Anchor>
</Container>
)
}
🙄 위의 코드를 설명하면,
Button 스타일 컴포넌트의 스타일을 그대로 가져와(확장하여)
Anchor 컴포넌트에 적용시킨다.
확장할 때는 styled.div
가 아니라 확장할 스타일 컴포넌트 이름을 사용하여 위와 같이 styled(Button)
을 사용한다.
Anchor를 <a> </a>
에 적용되는 스타일 컴포넌트로 만들고 싶다.
따라서 스타일 컴포넌트 속성 as
를 이용하여 <a/>
태그임을 알려준다.
a 태그의 속성인 href를 사용하여 이동할 주소를 넣어준다.
props의 사용은 styled-components의 굉장한 장점이다. className의 개수를 정말 많이 줄일 수 있다. 그리고 부분적, 동적 스타일 적용이 가능하다.
import styled, { css } from 'styled-components';
import React from 'react';
const Container = styled.div`
height:100vh;
width:100%;
background:blue;
& > .hello {
color:red;
}
`
const Button = styled.button`
border-radius: 50px;
padding:5px;
min-width:120px;
color:white;
font-weight: 600;
cursor:pointer;
-webkit-appearance: none;
&:active,
&:focus {
outline:none;
}
color:${props => props.danger? 'orange':'green'};
background:${props => props.color || 'blue'};
${props=>{
if(props.danger){
return css`
border-radius: 50px;
font-size: 1.4rem;
`
}
}}
}}
`
function App() {
return(
<Container>
<Button color='yellow'>Success</Button>
<Button danger>danger</Button>
</Container>
)
}
props를 이용한 스타일링을 이용해 Button 스타일 컴포넌트를 만들었다.
Button 컴포넌트의 color, background의 값을 props에 따라서 동적으로 변경될 수 있도록 하였다.
👉 css를 import하여 함수 형식으로 props를 다루고 css 코드 자체를 return하는 방식으로도 사용할 수 있다.
🎇이 부분!!🎇
${props=>{
if(props.danger){
return css`
border-radius: 50px;
font-size: 1.4rem;
`
}
CSS에서는 keyframes
와 Animation
속성을 이용하여 엘리먼트의 애니메이션을 제어하는데,
styled-components 에서도 이와 매우 비슷하다.🔥
우선 keyframes를 import 한다.
import styled, { keyframes } from 'styled-components';
function App(){
const rotation = keyframes`
from{
transform:rotate(0deg);
}
to{
transform:rotate(360deg);
}
`
const Button = styled.button`
background:red;
animation:${rotation} 2s 1s infinite alternate;
`
return(
<>
<Button> tempButton </Button>
</>
)
}
keyframes
를 이용하여 애니메이션을 만든다.
애니메이션을 적용시키고 싶은 스타일 컴포넌트에 애니메이션을 담은 변수를 ${}
로 넘겨주고 CSS에서 animation을 적용시키는 것 처럼 사용한다.
import styled from 'styled-components';
const Input = styled.input.attrs({
placeholder:'input placeholder',
className:'tempinput',
required:true
})`
border-radius: 5px;
background:yellow;
`
function App(){
return(
<>
<Input/>
</>
)
}
attrs({})
를 이용하여 태그의 속성 값을 바꿀 수 있으며, className
또한 속성 값이기 때문에 변경 가능하다. attrs({})
를 사용하여 속성을 변경한 후 위 코드와 같이 style을 지정해주면 된다.
mixin을 사용하기 위해서는 css
를 import 해야한다.
import styled, { css } from 'styled-components';
const rotation = keyframes `
from{
transform:rotate(0deg);
}
to{
transform:rotate(360deg);
}
`
const Card = css`
width:100px;
height:100px;
background:red;
animation: ${rotation} 2s 1s infinite;
`
const RedCard = styled.div`
${Card};
`
function App(){
return(
<>
<RedCard/>
</>
)
}
위 코드 처럼, mixin을 css
를 이용하여 선언해주고, CSS 내용을 저장한 변수를 스타일 컴포넌트에 그대로 적용해주면 된다. 위의 코드를 참고하면 된다.