[React] Styled Component의 모든 것

그릿 Grit·2022년 11월 8일
10

React

목록 보기
1/1
post-thumbnail
post-custom-banner

설치

npm i styled-components

vscode에서 styled component css syntax를 적용하고, 자동완성 기능을 사용해보고 싶다면, vscode-styled-components 익스텐션을 설치한다.

기본 구조

import styled from "styled-components";

// const 컴포넌트이름 = styled.HTML태그종류 `css 코드 그대로`;
const Box = styled.div`
  background-color: royalblue;
  width: 100px;
  height: 100px;
  border-radius: 15px;
`;

function App() {
  return <Box />;
}

export default App;

확장

prop을 통한 확장

css 구조가 거의 동일한데, 몇가지 속성만 다른 경우 사용한다.

const Box = styled.div`
  background-color: ${(props) => props.bgColor};
  width: 100px;
  height: 100px;
  border-radius: 15px;
`;

function App() {
  return (
    <Container>
      <Box bgColor="royalblue" />
      <Box bgColor="deeppink" />
    </Container>
  );
}

위의 예시는 background-color 속성만 다른 경우 사용하는 방법이다.

상속을 통한 확장

class에서 확장하는 것과 같이 상속을 통해 확장할 수도 있다. 이때는 styled() 함수를 사용하여 나타낸다. 상속을 하고 추가하고 싶은 코드만 넣어주면 된다.

//... 일부 생략
const Circle = styled(Box)`
  border-radius: 50px;
`;

function App() {
  return (
    <Container>
      <Box bgColor="royalblue" />
      <Box bgColor="deeppink" />
      <Circle bgColor="gold" />
    </Container>
  );
}

태그 변경을 위한 확장

확장이 아닌, 특정 styled component의 style을 그대로 가져오려면 어떻게 해야할까? 즉, style 부분은 그대로 쓰고, 태그 부분을 바꾸고 싶다면, as 속성을 사용하면 된다.

const Circle = styled(Box)`
  border-radius: 50px;
`;

const Text = styled.span`
  color: purple;
  font-size: 2rem;
  font-weight: bold;
`;

function App() {
  return (
    <>
      <Container>
        <Box bgColor="royalblue" />
        <Box bgColor="deeppink" />
        <Circle bgColor="gold" />
      </Container>
      <Text>Hello</Text>
      <Text as="a" href="/"> Home</Text>
    </>
  );
}

Text 컴포넌트는 원래 span 태그이지만, as="a" 속성을 줌으로써 a 태그로 바꿔서 사용할 수 있다.

태그 속성 설정

HTML 기본 속성 Default로 주기

// 형식
const styled_컴포넌트이름 =
      styled.HTML태그이름.attrs({ HTML_속성_이름: HTML_속성값 })`css 코드`;

attrs() 함수를 통해 인자로 HTML_속성_이름HTML_속성값을 짝지어 놓은 object를 넘겨주면, 해당 HTML_속성값이 default로 지정된 컴포넌트를 생성할 수 있다.

const Input = styled.input.attrs({ required: true })`
  display: block;
`;

function App() {
  return (
    <form>
      <Input placeholder="name" />
      <Input placeholder="phone number" />
      <Input placeholder="email" />
      <Input placeholder="birthday" />
    </form>
  );
}

모두 입력을 필수로 하는 input 태그를 생성할 수 있다.

애니메이션

// ⚠️ keyframes을 import 해주어야 한다.
import styled, { keyframes } from "styled-components";

// Animation의 정의
// animation 변수 keyframes helper function을 통해 만들기
const rotate = keyframes`
  from {
    transform: rotate(0deg);
  }
  to{
    transform:rotate(360deg);
  }
`;

// Animation이 추가된 styled component
const Elem = styled.div`
  background-color: royalblue;
  width: 100px;
  height: 100px;
  border-radius: 20px;
  animation: ${rotate} 3s linear infinite;
`;

function App() {
  return <Elem />;
}

Selector (선택자)

Pseudo Selector

일반 HTML 태그인 자식 element 선택하기

만약 아래 코드에서 스타일 컴포넌트가 아닌 자식 태그인 li를 선택해서 스타일을 주고 싶다면? 아래와 같이 li에 대한 css를 추가하면 된다.

const StyledUl = styled.ul`
  /*...css code*/
  li {
	color: whitesmoke;
  }
`;

function App() {
  return (
    <StyledUl>
      <li>this</li>
      <li>is</li>
      <li>the</li>
      <li>list</li>
    </StyledUl>
  );
}

위와 같이 부모인 sytled-component 자식 일반 엘리먼트들을 선택할 수 있다.

sytled-component인 자식 element 선택하기

자식도 컴포넌트가 일반 태그가 아니고, sytled-component인 경우도 선택자를 사용할 수 있다. 사용법은 아래와 같다.

// 커스텀 컴포넌트를 만들고
const List = styled.li`
  color: black;
`;

// 커스텀 컴포넌트를 선택자로 사용한다.
const StyledUl = styled.ul`
  /* ... css 코드 */
  ${List} {
    color: whitesmoke;
  }
`;

function App() {
  return (
    <StyledUl>
      <List as="span">this</List>
      <List>is</List>
      <List>the</List>
      <List>list</List>
    </StyledUl>
  );
}

state selector

&를 통해 자기자신에 대한 css를 추가적으로 정의할 수 있다.(:hover 과 같은 속성을 쉽게 정의해줄 수 있다.)

const List = styled.li`
  color: black;
  &:hover{
	color: white;
  }
`;

타입스크립트와의 사용법

Styled Components에도 타입을 지정해주어야 타입스크립트와 사용할 수 있다.

Type Definition 설치

Styled Component는 DefinitelyTyped에서 설치할 수 있다.

npm i --save-dev @types/styled-components

DefinitelyTyped 는 유명한 npm 라이브러리의 타입 definition을 담은 레퍼지토리이다. @types/의 파일 안에 정의되어 있다.

Interface를 통한 타입

필수가 아닌 스타일은 ? 를 통해 optional로 줄 수 있다.

interface ContainerProps {
	width: string;
  	bgColor?: string;
}

const Container = styled.div<ContainerProps>`
	width: 200px;
`;
profile
인디펜던트 워커 그릿 | 공부한 내용을 글로 담습니다. 👩🏻‍💻 instagram: @dev.grit
post-custom-banner

2개의 댓글

comment-user-thumbnail
2022년 11월 12일

오랫동안 사용한 라이브러리 였는데도 as의 사용법은 모르고 있었는데, 유용할 것 같네요! 감사합니다~

1개의 답글