[TIL] Styled Components

ํ˜ฑยท2023๋…„ 11์›” 7์ผ
1

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
25/85
post-thumbnail

Styled Component๋ž€?

๐Ÿ‘‰ styled-components๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋ฆฌ์•กํŠธ์—์„œ CSS-in-JS ๋ฐฉ์‹์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊พธ๋ฐ€์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ํŒจํ‚ค์ง€!

Styled Components ์ค€๋น„

(1) VSCode Extension ์„ค์น˜
์ด ์ต์Šคํ…์…˜์„ ์„ค์น˜ํ•˜๋ฉด styled-components์•ˆ์—์„œ ์Šคํƒ€์ผ ์ฝ”๋“œ๋ฅผ ํŽธํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค!

(2) styled-components ์„ค์น˜
npm install styled-components ๋˜๋Š”
yarn add styled-components

Styled Components ์‚ฌ์šฉ

(1) ๊ธฐ๋ณธ์ ์ธ ์‚ฌ์šฉ๋ฒ•

styled components์˜ ๊ธฐ๋ณธ์ ์ธ ์›๋ฆฌ๋Š” ๊พธ๋ฏธ๊ณ ์ž ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ styled components์˜ ๋ฐฉ์‹๋Œ€๋กœ ๋จผ์ € ๋งŒ๋“ค๊ณ , ๊ทธ ์•ˆ์— ์Šคํƒ€์ผ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

// App.js

import React from "react";
// styled-components์—์„œ styled ๋ผ๋Š” ํ‚ค์›Œ๋“œ๋ฅผ import ํ•ฉ๋‹ˆ๋‹ค.
import styled from "styled-components";

// styledํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ styled-components ๋ฐฉ์‹๋Œ€๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. 
const StBox = styled.div` 
  width: 100px;
  height: 100px;
  border: 1px solid red;
  margin: 20px;
`; // ์ด ์•ˆ์— ์Šคํƒ€์ผ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค. ์Šคํƒ€์ผ ์ฝ”๋“œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์•Œ๊ณ  ์žˆ๋Š” css์™€ ๋™์ผํ•˜๋‹ค.

const App = () => {
	// ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  styled-components๋ฅผ JSX์—์„œ html ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋“ฏ์ด ์‚ฌ์šฉํ•œ๋‹ค.
  return <StBox>๋ฐ•์Šค</StBox>;
};

export default App;


ํ•ต์‹ฌ : const StBox = styled.div``;
styled ๋’ค์—๋Š” html ํƒœ๊ทธ๊ฐ€ ์˜จ๋‹ค.
ex) styled.span, styled.button

(2) ์กฐ๊ฑด๋ถ€ ์Šคํƒ€์ผ๋ง

styled-components๋„ ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ์ปดํฌ๋„ŒํŠธ์ด๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์šฐ๋ฆฌ๋Š” ๊ฐ ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ props๋ฅผ ํ†ตํ•ด borderColor์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

import "./App.css";
import styled from "styled-components";

const StContainer = styled.div`
  display: flex;
`;
const StBox = styled.div`
  width: 100px;
  height: 100px;
  border: 1px solid ${(props) => props.$borderColor}; โญ๏ธ
  margin: 20px;
`;

function App() {
  return (
    <StContainer>
      <StBox $borderColor="red">์•ˆ๋…•</StBox>
      <StBox $borderColor="blue">์•ˆ๋…•</StBox>
      <StBox $borderColor="green">์•ˆ๋…•</StBox>
    </StContainer>
  );
}

export default App;

[๋™์ž‘ํ•˜๋Š” ๊ณผ์ •]
1. ๋จผ์ € ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ${ } ๋ฅผ ์—ด์–ด์ค๋‹ˆ๋‹ค.
2. ๋น„์–ด์žˆ๋Š” ํ™”์‚ดํ‘œ ํ•จ์ˆ˜๋ฅผ ์—ด์–ด ์ค๋‹ˆ๋‹ค. ${( )=>{ }} ์ด๋ ‡๊ฒŒ!
3. ํ•จ์ˆ˜์˜ ์ธ์ž์—์„œ props๋ฅผ ๋ฐ›์•„์˜ค๊ณ , props์•ˆ์—๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ณด๋‚ธ borderColor๊ฐ€ ์žˆ๋‹ค. ๊ทธ๊ฒƒ์„ return ํ•œ๋‹ค.
4. ${(props)โ‡’{ return props.$borderColor }} ์ด๋ ‡๊ฒŒ ๋ฆฌํ„ดํ•˜๋ฉด (props)โ‡’{ return props.$borderColor } ์˜ ๊ฐ’์ด === 'red' ๊ฐ€ ๋˜๊ณ  ๊ฒฐ๊ตญ ์šฐ๋ฆฌ ๋ˆˆ์—๋Š” ๋ณต์žกํ•ด๋ณด์ด์ง€๋งŒ, ๋ธŒ๋ผ์šฐ์ €๋Š” border: 1px solid red ๋ผ๋Š” ์ฝ”๋“œ๋กœ ์ธ์‹ํ•˜์—ฌ ์Šคํƒ€์ผ๋ง์ด ๋˜๋Š” ๊ฒƒ ์ด๋‹ค.

  • switch์™€ map์„ ํ†ตํ•œ refactoring
import "./App.css";
import styled from "styled-components";

const StContainer = styled.div`
  display: flex;
`;
const StBox = styled.div`
  width: 100px;
  height: 100px;
  border: 1px solid ${(props) => props.$borderColor};
  margin: 20px;
`;

const boxList = ["red", "blue", "green", "black"];

const getBoxName = (color) => {
  switch (color) {
    case "red":
      return "๋นจ๊ฐ„ ๋ฐ•์Šค";
    case "blue":
      return "ํŒŒ๋ž€ ๋ฐ•์Šค";
    case "green":
      return "์ดˆ๋ก ๋ฐ•์Šค";
    default:
      return "๊ฒ€์ • ๋ฐ•์Šค";
  }
};
function App() {
  return (
    <StContainer>
      {boxList.map((box, idx) => (
        <StBox key={idx} $borderColor={box}>
          {getBoxName(box)}
        </StBox>
      ))}
    </StContainer>
  );
}

export default App;

Global Style

(1) Global Style (์ „์—ญ ์Šคํƒ€์ผ) ์ด๋ž€?

์šฐ๋ฆฌ๋Š” ํ”„๋กœ์ ํŠธ์— ๊ณตํ†ต์ ์œผ๋กœ ์ ์šฉํ•ด์•ผ ํ•  ์Šคํƒ€์ผ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋Ÿด ๋•Œ ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋ฐ”๋กœ ์ „์—ญ ์Šคํƒ€์ผ๋ง ์ด๋‹ค.

(2) ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„ ์Šคํƒ€์ผ๋ง

// TestPage.jsx
import styled from "styled-components";

function TestPage(props) {
  return (
    <Wrapper>
      <Title>{props.title}</Title>
      <Contents>{props.contents}</Contents>
    </Wrapper>
  );
}

const Title = styled.h1`
  font-family: "Helvetica", "Arial", sans-serif;
  line-height: 1.5;
  font-size: 1.5rem;
  margin: 0;
  margin-bottom: 8px;
`;

const Contents = styled.p`
  margin: 0;
  font-family: "Helvetica", "Arial", sans-serif;
  line-height: 1.5;
  font-size: 1rem;
`;

const Wrapper = styled.div`
  border: 1px solid black;
  border-radius: 8px;
  padding: 20px;
  margin: 16px auto;
  max-width: 400px;
`;

export default TestPage;

๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์— font-family์™€ line-height์†์„ฑ์ด ๊ณตํ†ต์ ์œผ๋กœ ๋“ค์–ด์žˆ๋‹ค.
์ด๋•Œ ๊ณตํ†ต์ ์œผ๋กœ ์ ์šฉ๋˜๋Š” ๋ถ€๋ถ„์€ ๋นผ์„œ global style๋กœ ์ ์šฉํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค.

(3) Global Style ์ ์šฉ

// GlobalStyle.jsx
import { createGlobalStyle } from "styled-components";

const GlobalStyle = createGlobalStyle`
  body {
    font-family: "Helvetica", "Arial", sans-serif;
    line-height: 1.5;
  }
`;

export default GlobalStyle;
// App.jsx
import GlobalStyle from "./GlobalStyle";
import BlogPost from "./BlogPost";

function App() {
	const title = '์ „์—ญ ์Šคํƒ€์ผ๋ง ์ œ๋ชฉ์ž…๋‹ˆ๋‹ค.';
	const contents = '์ „์—ญ ์Šคํƒ€์ผ๋ง ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.';
  return (
    <>
      <GlobalStyle /> // ์ตœ์ƒ์œ„
      <BlogPost title={title} contents={contents} />
    </>
  );
}

export default App;

๊ธ€๋กœ๋ฒŒ ์Šคํƒ€์ผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฃจํŠธ ์ตœ์ƒ์œ„์— ๋„ฃ์–ด์ฃผ๋ฉด ํ•˜์œ„์˜ ์ปดํฌ๋„ŒํŠธ๋“ค์—๊ฒŒ ๊ธ€๋กœ๋ฒŒ ์Šคํƒ€์ผ์ด ์ ์šฉ๋œ๋‹ค.

๋Š๋‚€์ 

์–ด๋ ค์šด ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ต์ˆ™ํ•˜์ง€ ์•Š์€ ๊ฒƒ์ด๋‹ค!๐Ÿ˜ค
๊ณ„์† ์‚ฌ์šฉํ•ด๋ณด๋ฉด์„œ ์ต์ˆ™ํ•ด์งˆ ํ•„์š”๊ฐ€ ์žˆ๋‹ค.

profile
๋Š๋ฆฌ๋”๋ผ๋„ ์กฐ๊ธˆ์”ฉ, ๊พธ์ค€ํžˆ

0๊ฐœ์˜ ๋Œ“๊ธ€