본문 바로가기

React

[React] styled-components

styled-components 홈페이지

 

styled-components

CSS for the <Component> Age

styled-components.com

설치

npm i styled-components

tip: vscode-styled-components

vscode extension인 vscode-styled-components를 받으면 자동 완성 및 하이라이트 기능 제공

 

without styled-components

 

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

export default App;

 

with styled-components

  • styled 뒤에 속성 값을 back tick 사이에 입력
  • back tick 안에 들어간 내용은 일반 css로 작성
  • 실제 페이지에서 검사도구로 확인할 경우, 임의의 class 이름이 부여된 것을 확인 가능
import styled from "styled-components";

const Father = styled.div`
  display: flex;
`;

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

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

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

export default App;

Problem

styled-components내에 중복되는 부분을 어떻게 효율적으로 작성할 수 있을까?

Scratch1; component에 props 받기

import styled from "styled-components";

const Father = styled.div`
  display: flex;
`;

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

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

export default App;
```

Scratch 2; 기존의 styled-component 상속

상속 전
import styled from "styled-components";

const Father = styled.div`
  display: flex;
`;

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

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

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

export default App;

 

상속 후: Cicle에서 기존 Box를 상속 받음
import styled from "styled-components";

const Father = styled.div`
  display: flex;
`;

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

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

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

export default App;

Scratch3; as

as는 기존의 만들어진 styled-components를 html tag만 변경하여 사용할 수있게 해준다
import styled from "styled-components";

const Father = styled.div`
  display: flex;
`;

const Btn = styled.button`
  color: white;
  background-color: tomato;
  border: 0;
  border-radius: 15px;
`;

function App() {
  return (
    <Father>
      <Btn>Log-in</Btn>
      <Btn as="a">Log-in</Btn>
    </Father>
  );
}

export default App;

Scratch 4; attrs

attrs를 사용하여 각 styled-components에 속성 부여를 해준다
import styled from "styled-components";

const Father = styled.div`
  display: flex;
`;

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

function App() {
  return (
    <Father>
      <Input />
      <Input />
      <Input />
      <Input />
    </Father>
  );
}

export default App;

keyframe

keyframe을 사용한 애니메이션 적용 예시

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

const Wrapper = styled.div`
  display: flex;
`;

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

const Box = styled.div`
  height: 200px;
  width: 200px;
  background-color: salmon;
  animation: ${rotationAnimaiton} 1s linear infinite;
`;

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

export default App;

Pseudoelements, pseudoselectors, and nesting

styled-components 안에서 일반 html tag를 선택할 수 있음
styled-components 안에서 pseudo selector를 선택할 수 있음

 

import styled from "styled-components";

const Wrapper = styled.div`
  display: flex;
`;

const Box = styled.div`
  height: 200px;
  width: 200px;
  background-color: salmon;
  display: flex;
  justify-content: center;
  align-items: center;
  span {
    font-size: 36px;
    &:hover {
      font-size: 72px;
    }
  }
`;

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

export default App;
styled-components 안에서 styled-components를 선택할 수도 있음
import styled, { keyframes } from "styled-components";

const Wrapper = styled.div`
  display: flex;
`;

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

const Emoji = styled.span`
  font-size: 36px;
`;

const Box = styled.div`
  height: 200px;
  width: 200px;
  background-color: salmon;
  display: flex;
  justify-content: center;
  align-items: center;
  animation: ${rotationAnimaiton} 1s linear infinite;
  ${Emoji} {
    &:hover {
      font-size: 72px;
    }
  }
`;

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

export default App;

theme

  • 기본적으로 모든 색상을 가지고 있는 object
  • local estate management와 응용하면 다크모드 구현 가능
  • App을 ThemeProvider로 감싸줌
  • theme 간의 property 이름은 같아야함
// index.js
import React from "react";
import ReactDOM from "react-dom/client";
import { ThemeProvider } from "styled-components";
import App from "./App";

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

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

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <ThemeProvider theme={darkTheme}>
    <App />
  </ThemeProvider>
);
ThemeProvider의 값에 접근 가능
// App.js
import styled from "styled-components";

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

const Title = styled.h1`
  color: ${(props) => props.theme.textColor};
`;

function App() {
  return (
    <Wrapper>
      <Title>Title</Title>
    </Wrapper>
  );
}

export default App;

'React' 카테고리의 다른 글

[React] 가상화폐시세 사이트 1 - CSS reset  (0) 2023.08.29
[React] TypeScript  (0) 2023.08.17
[React 기초] 08. 예제 - Movie info  (0) 2023.08.10
[React 기초] 07. 예제 - Coin tracker  (0) 2023.08.10
[React 기초] 06. 예제 - Todo List  (0) 2023.08.10