[CSS] CSS-in-JS의 Styled-Components 사용법 및 문법 정리

2023. 9. 16. 13:34·◼ FrontEnd/Web & HTML, CSS
반응형

CSS-in-JS란?

  • 자바스크립트 파일 안에서 CSS를 작성할 수 있는 방법이다.

  • 자바스크립트의 상태 값을 공유하여 동적으로 스타일링을 하기 위해 등장한 패러다임이다.

    • 인라일 스타일 이용 or 클래스 명으로 조건부 스타일링 <- 문제점이 있음

      • (전자: 스타일 재사용 X, 후자: 클래스 이름 중복 문제)

CSS-in-JS의 장점

  • JS 파일 안에서 CSS 코드를 작성하기 때문에 CSS의 변수와 함수를 그대로 사용할 수 있다.

  • 클래스 명이 해시 값으로 치환되기 때문에 클래스 이름의 중복 및 작명에 대한 걱정을 덜 수 있다.

  • 현대 웹은 컴포넌트를 기반으로 발전하고 있으므로, 컴포넌트와 스타일을 하나의 파일에서 작성하는 CSS-in-JS는 모듈화가 수월해진다.



Styled Components

  • CSS-in-JS에는 여러 종류의 라이브러리가 있는데, 2022년 기준 가장 많이 사용되는 라이브러리가 styled-components이다.

설치

npm install styled-components



Styled Components 사용법 및 문법

const [컴포넌트명] = styled.[html태그]`
  [부여하고자 하는 css속성]
`;
// 사용 예시
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;
  • vscode-styled-components 익스텐션 : styled-component css 자동완성 기능 제공

컴포넌트의 props 속성값에 따라 서로 다른 스타일 부여하기 - ${(props) => props.[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;
  • 이 문법을 활용하면 중복되는 스타일 코드를 하나로 나타낼 수 있으므로 코드가 더욱 깔끔해진다.

컴포넌트 스타일 확장하기 - styled([컴포넌트])

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="tomato" />
    </Father>
  );
}

export default App;

컴포넌트의 HTML 태그 재설정하기 - as props

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 as="header">
      <Btn>Log In</Btn>
      <Btn as="a" href="/">
        Log In
      </Btn>
    </Father>
  );
}

export default App;
<div id="root">
  <header class="sc-dIfARi kqAazX">
    <button class="sc-hHTYSt iKcUmj">Log In</button
    ><a href="/" class="sc-hHTYSt iKcUmj">Log In</a>
  </header>
</div>
  • 스타일은 그대로 두되, 컴포넌트의 태그를 바꾸고자 할 때 as props를 활용한다.

컴포넌트의 HTML 태그에 속성 직접 추가하기 - styled.[태그].attrs({ [속성] })

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 as="header">
      <Input></Input>
      <Input></Input>
      <Input></Input>
      <Input></Input>
      <Input></Input>
    </Father>
  );
}

export default App;
<div id="root">
  <header class="sc-fLcnxK hjukqa">
    <input required="" class="sc-bBABsx iPtiKZ" minlength="10" /><input
      required=""
      class="sc-bBABsx iPtiKZ"
      minlength="10"
    /><input required="" class="sc-bBABsx iPtiKZ" minlength="10" /><input
      required=""
      class="sc-bBABsx iPtiKZ"
      minlength="10"
    /><input required="" class="sc-bBABsx iPtiKZ" minlength="10" />
  </header>
</div>

styled-components 안에서 애니메이션 추가하기

  • 우선 helper 함수인 keyframes를 import 해주어야 한다.
import styled, { keyframes } from "styled-components";

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

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

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

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

export default App;

styled-components 가상 선택자

import styled from "styled-components";

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

const Box = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  height: 200px;
  width: 200px;
  background-color: tomato;

  span {
    font-size: 36px;

    &:hover {
      font-size: 40px;
    }
    &:active {
      opacity: 0;
    }
  }
`;

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

export default App;
import styled from "styled-components";

const Wrapper = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100vw;
  height: 100vh;
`;

const Emoji = styled.span``;

const EmojiTwo = styled.span``;

const Box = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  height: 200px;
  width: 200px;
  background-color: tomato;

  ${Emoji} {
    font-size: 36px;

    &:hover {
      font-size: 90px;
    }
    &:active {
      opacity: 0;
    }
  }

  ${EmojiTwo}:hover {
    font-size: 90px;
  }
`;

function App() {
  return (
    <Wrapper>
      <Box>
        <Emoji>🙂</Emoji>
        <EmojiTwo>🙁</EmojiTwo>
      </Box>
    </Wrapper>
  );
}

export default App;

theme

  • 모든 색상을 가지고 있는 Object
// 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(
  <React.StrictMode>
    <ThemeProvider theme={darkTheme}>
      <App />
    </ThemeProvider>
  </React.StrictMode>
);
// App.js
import styled, { keyframes } from "styled-components";

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

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

// ... (코드 생략) ...

function App() {
  return (
    <Wrapper>
      <Title>Hello</Title>
      <Box>
        <Emoji>🙂</Emoji>
        <EmojiTwo>🙁</EmojiTwo>
      </Box>
    </Wrapper>
  );
}

export default App;

전역 스타일링

// GlobalStyle.jsx (예시)
import { createGlobalStyle } from "styled-components";
import reset from "styled-reset";

const GlobalStyle = createGlobalStyle`
  ${reset}

  * {
    box-sizing: border-box;
    font-family: 'Do Hyeon', sans-serif;
    text-decoration: none;
    font-size: 0.625rem;
    margin: 0px;
    padding: 0px;
    list-style: none;
  }

  body {
    background-image: url('./images/background-2426328_1920.jpg');
    background-size: 100%;
    height: 100%;
    overflow: hidden;
  }
`;

export default GlobalStyle;
// index.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import { ThemeProvider } from "styled-components";
import { RouterProvider } from "react-router-dom";
import router from "./Router";
import reportWebVitals from "./reportWebVitals";
import GlobalStyle from "./styles/GlobalStyle";
import GlobalFont from "./styles/GlobalFont";
import theme from "./styles/theme";
import variables from "./styles/variables";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <ThemeProvider theme={{ theme, variables }}>
    <GlobalStyle />
    <GlobalFont />
    <RouterProvider router={router} />
  </ThemeProvider>
);

reportWebVitals();

반응형

'◼ FrontEnd > Web & HTML, CSS' 카테고리의 다른 글

[Web] PWA(프로그래시브 웹 앱)이란 무엇일까?  (2) 2023.05.12
[Web] CSR과 SSR이란 무엇일까?  (0) 2023.05.03
[NodeJS] Node JS & NPM 소개 및 설치  (0) 2023.01.22
CSS 레이아웃 - Position과 Block 정리  (0) 2022.10.23
Semantic Tag (시멘틱 태그) 를 사용하여 웹 개발을 해야하는 이유  (0) 2022.10.23
'◼ FrontEnd/Web & HTML, CSS' 카테고리의 다른 글
  • [Web] PWA(프로그래시브 웹 앱)이란 무엇일까?
  • [Web] CSR과 SSR이란 무엇일까?
  • [NodeJS] Node JS & NPM 소개 및 설치
  • CSS 레이아웃 - Position과 Block 정리
SangYoonLee (SYL)
SangYoonLee (SYL)
Slow, But Steady Wins The Race 😎
    반응형
  • SangYoonLee (SYL)
    ◆ Slow, But Steady ◆
    SangYoonLee (SYL)
  • 전체
    오늘
    어제
    • ◻ 전체 글 수 : (131)
      • ✪ 취미, 경험 회고 및 일상 (26)
        • [취미] Room Escape (2)
        • [회고] IT 관련 경험 회고 (18)
        • [일상] 일상 생각 (4)
        • [일상] 독후감 (1)
      • ◼ FrontEnd (29)
        • Web & HTML, CSS (8)
        • JavaScript (4)
        • TypeScript (1)
        • ReactJS (16)
      • ◼ CS (3)
        • 자료구조 & 알고리즘 (1)
        • 컴퓨터 구조 (1)
        • 운영체제 (1)
      • ◼ PS Note (40)
        • 백준 (38)
        • 프로그래머스 (2)
      • ◼ IT Etc. (33)
        • (Until 2021) (21)
        • Python (6)
        • C | C# | C++ (1)
        • Git (1)
        • Unity (4)
        • Game Dev. (0)
  • 블로그 메뉴

    • 홈
    • 💻 GitHub
    • 🟢 Velog
    • 🧩 온라인 방탈출 출시 작품 모음
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    후기
    회고
    리엑트
    더라비린스
    C++
    pygame
    유니티
    wecode
    개인 프로젝트
    알고리즘
    Cpp
    위코드
    관심사의 분리
    1929
    미궁 게임
    주간 회고
    React
    unity
    JavaScript
    CodeSoom
    Python
    소수 구하기
    프로젝트
    Component
    프로그래머스
    파이썬
    코드숨
    백준
    코딩 일기
    방탈출고사
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
SangYoonLee (SYL)
[CSS] CSS-in-JS의 Styled-Components 사용법 및 문법 정리
상단으로

티스토리툴바