오늘도 코딩하나

[React] Styled-Component로 동적 스타일링과 테마 적용하기 본문

React/노마드코더

[React] Styled-Component로 동적 스타일링과 테마 적용하기

오늘도 코딩하나 2025. 1. 15. 02:24
강의 내용 요약 : 강의 링크
#2.0 ~ #2.7

 

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(Box)`
  border-radius: 50px;
`;

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

export default App;
  • style과 구현 부분으로 나누어지고, 구현 부분은 훨씬 가독성이 좋아진다.
  • bgColor : props를 사용하여 동적으로 스타일 변경가능
  • Circle : 기존 styled-component(Box)를 확장하여 새로운 컴포넌트 생성 가능

 

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

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

function App() {
  return (
    <Father>
      <Btn as="header">Login</Btn>
      <Btn as="a" href="/">
        Login
      </Btn>
      <Input />
      <Input />
      <Input />
      <Input />
      <Input />
    </Father>
  );
}
  • as : HTML 요소를 동적으로 변경 가능
  • 모든 Input에 readonly 속성을 주고 싶은 경우, styled-component에 attrs 메서드를 사용하여 속성 추가 가능

 

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

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`
  height: 200px;
  width: 200px;
  background-color: tomato;
  display: flex;
  justify-content: center;
  align-items: center;
  animation: ${rotationAnimation} 1s linear infinite;
  span {
    font-size: 36px;
    &:hover {
      font-size: 40px;
    }
    &:active {
      opacity: 0;
    }
  }
`;

function App() {
  return (
    <Wrapper>
      <Box>
        <span>😀</span>
      </Box>
    </Wrapper>
  );
}
  • rotationAnimation : keyframes를 사용하여 정의된 CSS 애니메이션
  • 꼭 모든 component에 styled component 처리를 해 줄 필요는 없다.
    대신! 그냥 한 component만 styled 처리해주고 다른건 target 처리해주면 된다.

 

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

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

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

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

function App() {
  return (
    <Wrapper>
      <Box>
        <Emoji>😀</Emoji>
      </Box>
      <Emoji>☠</Emoji>
    </Wrapper>
  );
}
  • span을 별도의 Emoji 컴포넌트로 분리
  • Box내에서만 hover 상태에서의 속성 추가

 

✅ darkmode / lightmode 만들기

- index.js

import React from "react";
import ReactDOM from "react-dom/client";
import { ThemeProvider } from "styled-components";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));

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

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

root.render(
  <React.StrictMode>
    <ThemeProvider theme={lightTheme}>
      <App />
    </ThemeProvider>
  </React.StrictMode>
);
  • ThemeProvider : styled-components에서 제공하는 컴포넌트, 하위 컴포넌트에 테마를 공급
  • darkTheme, lightTheme : 동일하게 textColor, backgroundColor 적용
    → 하위 컴포넌트에서 props.theme로 접근 가능

- App.js

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

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

const Wrapper = styled.div`
  display: flex;
  height: 100vh;
  width: 100vw;
  justify-content: center;
  align-items: center;
  background-color: ${(props) => props.theme.backgroundColor};
`;

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

export default App;
  • Theme에 대한 reference를 가지고 있어
    theme이 darkmode / lightmode에 따라 자동으로 color, background-color 적용됨