Styled-Components 완전정복

김주형·2023년 3월 6일
0

styled-components는 css-in-js 형태로 리액트 컴포넌트 내에서 스타일링 할 수 있는 라이브러리이며 따로 css module을 생성하지 않아도 된다는 장점이 있다. (개인적으로 이 방식이 가장마음에 든다)

설치

우선 설치부터

yarn add --dev @types/styled-components // ts
yarn add styled-components // js

typescript에서 오류없이 사용하기 위해서는 styled-component의 type들을 가지고 와야합니다.

사용법

1.가장 기본적인 사용법

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;

2.원하는 styled-component에 props로 속성을 지정할 수 있다.

예를 들어 위 코드에서 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의 타입을 미리 정의하고 전달해줘야한다!!!!!!!!!!

3.스타일드 컴포넌트 상속 및 어트리뷰트 지정

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,...}) 식으로 지정할 수 있다.

4.animation 사용 , pseudo selector

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 등 애니메이션을 줄 때 유용하다.

ThemeProvider

보통 다크모드,라이트모드 구현 이나 전체 프로젝트의 스타일을 정의할때 사용된다. (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>
);
profile
프론트엔드 개발 지망생입니다.

0개의 댓글