Tech/Styling

styled-components 파헤치기 (feat. 리액트)

닝닝깅 2023. 1. 2. 01:14

리액트에서 스타일을 입히는데 현재 가장 많이 쓰이는 기술은 styled components 이다.

 

 

우선 사용을 위해 설치를 해준다.

npm i styled-components

 

스타일 컴포넌트 사용 전 우리가 흔히 사용하는 방법이다.

function App() {
  return (
    <div style={{ backgroundColor: "tomato", width: 100, height: 100 }}></div>
  );
}

태그에 일일이 스타일 속성값을 넣어주거나 클래스명을 따로 부여하고 css파일에서 작업해야 한다.

 

 

같은 스타일을 입힌다고 했을 때 스타일 컴포넌트 사용하게 되면 아래와 같아진다.

import styled from "styled-components";

const BoxOne = styled.div`
  background-color: tomato;
  width: 100px;
  height: 100px;
`;

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

스타일 컴포넌트는 태그에 자동으로 임의의 클래스명을 부여하여 스타일을 입힌다.

 

만약 해당 예시에서 background-color가 다른 색인 스타일 컴포넌트가 필요하면 어떻게 해야할까?

하나의 변경값이 있다고 새로운 컴포넌트를 만드는 건 코드가 중복되기 때문에 비효율적이다.

스타일 컴포넌트는 해당 값을 변경 가능한 속성으로 두고 props로 값을 받아 쉽게 해결할 수가 있다.

 

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

function App() {
  return (
    <div>
      <Box bgColor="tomato"/>
      <Box bgColor="teal"/>
    </div>
  );
}

이와같이 컴포넌트에 props를 보내서 사용하면 된다.

 

**

아예 기존 컴포넌트의 스타일 속성을 모두 가져와 확장하여 새로운 컴포넌트를 만들고 싶을 때가 있을 것이다.

이땐 styled 함수의 사용법을 살짝 바꾸어 사용한다.

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

**

그러면 같은 종류의 태그에만 적용이 가능한가?

컴포넌트의 태그는 바꾸고 싶지만 스타일은 바꾸고 싶지 않을 때는 컴포넌트에 as라는 props를 보낸다.

  return (
    <div>
      <Box as="button" />
    </div>
  );

**

스타일 속성 말고 minLength, required 와 같은 다른 속성값을 스타일 컴포넌트 내에서 지정할 수도 있다.

attrs( )를 사용하여 컴포넌트에 전달되는 모든 속성을 가진 오브젝트를 담을 수 있다.

const Input = styled.input.attrs({ required: true, minLength:10 })`
  background-color: tomato;
`;

**

스타일 컴포넌트에도 애니메이션을 주는 방법을 알아보자.

우선 key frame이라는 함수를 import하여 사용한다.

import styled, { keyframes } from "styled-components";

const rotationAnimation = keyframes`
0%{
  transform: rotate(0deg);
  border-radius: 0px;
}
50%{
  border-radius: 100px;
}
100%{
  transform: rotate(360deg);
  border-radius: 0px;
}`;

 

생성한 애니메이션을 적용하고 싶으면 아래와 같이 하면 된다.

const Box = styled.div`
  animation: ${rotationAnimation} 1s linear infinite;
`;

 

**

span은 일반 html태그인데 Box 스타일 컴포넌트에서 속성값을 줄 수 있다.

function App() {
  return (
    <Wrapper>
      <Box>
        <span>😀</span>
      </Box>
    </Wrapper>
  );
}
const Box = styled.div`
  span {
    font-size: 40px;
  }
`;

하나의 컴포넌트만 스타일 컴포넌트로 처리하고 span은 타겟 처리 할 수 있다.

 

hover 값을 주고 싶다면 css처럼 span: hover{ }로 처리할 수도 있지만 좀 더 간편한 방법이 있다.

 span {
    font-size: 40px;
    &:hover {
      font: 60px;
    }
  }

 

만약 일반 태그가 아닌 스타일 컴포넌트를 타겟팅 하고 싶으면 ${컴포넌트 이름} 으로 동일하게 처리하면 된다.

 

##Themes

 Themes는 모든 색상을 넣어둔 object이다.

 

index.js에서 ThemeProvider을 import 해준다.

그리고 색상을 명시한 프로퍼티에 값을 준다.

import { ThemeProvider } from "styled-components";

const darkTheme = {
  textColor: "whitesmoke",
  backgroundColor: "#111",
};

App 컴포넌트를 ThemeProvider로 감싼다.

ReactDOM.render(
  <React.StrictMode>
    <ThemeProvider theme={darkTheme}>
      <App />
    </ThemeProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

App 내에서 Theme의 색상을 사용하고 싶으면 프로퍼티를 파라미터로 전달한다.

const Box = styled.div`
  background-color: ${(props) => props.theme.backgroundColor};
`;