styled-components는 css-in-js 형태로 리액트 컴포넌트 내에서 스타일링 할 수 있는 라이브러리이며 따로 css module을 생성하지 않아도 된다는 장점이 있다. (개인적으로 이 방식이 가장마음에 든다)
우선 설치부터
yarn add --dev @types/styled-components // ts
yarn add styled-components // js
typescript에서 오류없이 사용하기 위해서는 styled-component의 type들을 가지고 와야합니다.
const Wrapper = styled.div`
display: flex;
gap: 10px;
`;
const Box = styled.div`
width: 300px;
height: 200px;
`;
function App() {
return (
<Wrapper>
<Box />
<Box />
</Wrapper>
);
}
export default App;
예를 들어 위 코드에서 Box라는 스타일드 컴포넌트중 하나는 background-color 를 green , 다른 하나는 yellow로 주고 싶을때 props를 주지 않는다면 일일히 작성해야하는 번거로움 + 코드가 중복되는 부분이 많아짐
props를 적용한 코드
interface BColor {
bgColor: string;
}
...
const Box = styled.div`
width: 300px;
height: 200px;
background-color: ${(props) => props.bgColor};
`;
function App() {
return (
<Wrapper>
<Box bgColor='teal' />
<Box bgColor='tomato' />
</Wrapper>
);
}
Box 컴포넌트에 props로 bgColor를 전달해주면 해당 컴포넌트에서 ${props=>props.bgColor} 로 props의 값을 전달 받을 수 있다.
타입스크립트는 컴포넌트가 주려는 props의 타입을 단언할 수 없기 때문에 반드시 props의 타입을 미리 정의하고 전달해줘야한다!!!!!!!!!!
const Button = styled.button<BColor>`
background-color: ${(props) => props.bgColor};
`;
const Link = styled(Button)`
width: 200px;
height: 300px;
`;
const Input = styled.input.attrs({ required: true, minLength: 10 })`
background: tomato;
`;
function App() {
return (
<Wrapper>
...
<Button bgColor='grey' />
<Link bgColor='green' as='a' />
<Input />
</Wrapper>
);
}
버튼 컴포넌트의 background-color 속성을 상속받고 새로운 속성을 정의하는 Link 컴포넌트이다. 주의할 점은 styled(~)에 유의하자
스타일드 컴포넌트에 as 어트리뷰트를 사용해 브라우저에게 태그의 용도를 바꿔줄 수 있다. 위 코드는 button 을 a 로 인식하도록 as='a' 어트리뷰트로 설정하였다.(div,span,a,... 다 가능)
만약 스타일드 컴포넌트에서 스타일링 할 때 원하는 어트리뷰트를 미리 지정하고 싶다 하면 .attrs({required:true,...}) 식으로 지정할 수 있다.
styled-component에서는 keyframes 를 사용해 animation을 비교적 쉽게 사용할 수 있다.
import styled, { keyframes } from 'styled-components';
...
const RotateAnimation = keyframes`
0%{
transform:rotate(0deg)
}
100%{
transform:rotate(360deg)
}
`;
const Emoji = styled.span`
font-size: 36px;
`;
const Box = styled.div<IColor>`
width: 300px;
height: 200px;
background-color: ${(props) => props.bgColor};
animation: ${RotateAnimation} 1s ease-in;
${Emoji} {
&:hover {
font-size: 100px;
}
}
`;
function App() {
return (
<Wrapper>
<Box bgColor='tomato'>
<Emoji>hi</Emoji>
</Box>
</Wrapper>
);
}
단 keyframes로 animation을 먼저 선언한 뒤 사용해야한다.
styledcomponent는 pseudo selector로 스타일링하는 컴포넌트 내에서 다른 컴포넌트를 지정할 수 있다.
& -> 자기 자신을 가리킴
${Emoji} -> 스타일링 된 이모지 태그를 가리킴
태그 -> Box 안에 있는 태그를 가리킴
주로 hover , active 등 애니메이션을 줄 때 유용하다.
보통 다크모드,라이트모드 구현 이나 전체 프로젝트의 스타일을 정의할때 사용된다. (GlobalStyle 로 지정하는 경우도 있음)
styled-components의 ThemeProvider는 context api 기반으로 만들어진 것으로, Context api의 방식대로 Provier로 감싼 Component들은 theme정보를 props형태로 넘겨받아서 사용 할 수 있습니다.
아래는 darkmode , lightmode의 예시입니다.
1.우선 style.d.ts 라는 폴더를 만들어 theme 의 타입을 정의해 줍니다.
//style.d.ts
// import original module declarations
import 'styled-components';
// and extend them!
declare module 'styled-components' {
export interface DefaultTheme {
textColor:string,
bgColor:string,
btnColor:string
}
}
2.theme.ts 에서 앞서 선언한 DefaultTheme의 타입으로 theme 속성을 정의해줍니다.
// theme.ts
import { DefaultTheme } from 'styled-components';
// 다크모드 , 라이트모드를 가지려면 css의 property가 같아야한다.
export const lightTheme:DefaultTheme = {
bgColor:'white',
textColor:'black',
btnColor:'tomato'
}
export const darkTheme:DefaultTheme = {
bgColor:'black',
textColor:'white',
btnColor:'teal'
}
3.사용하려는 컴포넌트의 최상단 부모를 ThemeProvider로 감싸고 theme props를 넘겨줍니다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ThemeProvider } from 'styled-components';
import { lightTheme, darkTheme } from './theme';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<ThemeProvider theme={lightTheme}>
<RouterProvider router={router} />
</ThemeProvider>
</React.StrictMode>
);