15-2강. styled-components

정원·2023년 2월 7일
0

React

목록 보기
35/42

2023.02.07 styled-components

styled-components

styled-components는 CSS 문법을 그대로 사용하면서 결과물을 스타일링된 컴포넌트 형태로 만들어주는 오픈소스 라이브러리입니다.
미니 프로젝트를 진행할 때 사용할 예정이기 때문에 간단하게 배워봅시다.

styled-components 설치하기

#npm을 사용하는 경우
npm install --save styled-components

#yarn을 사용하는 경우
yarn add styled-components

vscode에서 자동완성을 위해 라이브러리 추가

test

MainPage.jsx를 만들어 test해보자.

MainPage.jsx

import React from "react";
import styled from "styled-components";

const Wrapper = styled.div`
    padding: 1em;
    background: grey;
`;

const Title = styled.h1`
    font-size: 1.5em;
    color: white
    text-align: center;
`;

function MainPage(props) {
    return (
        <Wrapper>
            <Title>
                안녕, 리액트
            </Title>
        </Wrapper>
    )
}

export default MainPage;

index.js

수정 후 브라우저를 띄우면 아래와 같이 잘 작동하는것을 볼 수 있습니다.

styled-components 기본 사용법

styled-components는
태그드 템플릿 리터럴(tagged template literal)을 사용하여 구성 요소의 스타일을 지정합니다.
여기에서 템플릿 리터럴이라는 것이 등장하는데 이것은 자바스크립트에서 제공하는 문법 중 하나입니다.

리터럴(literal)

프로그래밍에서 리터럴은 소스코드의 고정된 값을 의미합니다.
흔히 상수와 헷갈려 하는 경우가 있는데 둘은 다른 개념입니다.

위의 그림을 보면 대입 연산자(=)의 왼쪽에는 number라는 이름의 변수가 등장하고
오른쪽에는 정수 20이 등잡합니다.
여기에서 오른쪽에 있는 정수 20이 바로 리터럴입니다.
소스코드 상에 있는 고정된 값을 의미하는 것이죠.

다양한 종류의 literal

// 정수 리터럴(Integer literal)
cosnt myNumber = 10;

// 문자열 리터럴(String literal)
const myStr = 'Hello';

// 배열 리터럴(Array literal)
const myArray = [];

// 객체 리터럴(Object literal)
const myObject = {};

변수를 선언할 때 var나 let을 사용하지 않고 상수를 의미하는 const를 사용했는데,
이렇게 선언하게 되면 해당 변수들이 모두 상수가 됩니다.
그리고 대입 연산자(=)의 오른쪽에 있는 값이 모두 리터럴이 됩니다.

템플릿 리터럴?

템플릿 리터럴은 말 그대로 리터럴을 템플릿 형태로 사용하는 자바스크립트의 문법인데,
backticks(`)를 사용하여 문자열을 작성하고 그 안에 대체 가능한 expression을 넣는 방법입니다.
여기에서 이 expression을 대체라는 뜻을 가진 substiution이라고 부릅니다.

템플릿 리터럴은 또 크게 언태그드 템플릿 리터럴태그드 템플릿 리터럴로 나뉩니다.

// Untagged template literal
// 단순한 문자열
`string text`

// 여러 줄(Multi-line)에 걸친 문자열
`string text line1
 string text lin2`

// 대체 가능한 expression이 들어있는 문자열
`string text ${exprssion} string text`
// Tagged template literal
// myFunction의 파라미터로 expression으로 구분된 문자열 배열과 expression이 순서대로 들어간 형태로 호출됨
myFunction`string text ${expressoin} string text`;

위 코드에 나온 것처럼
언태그드 템플릿 리터럴은 보통 문자열을 여러 줄에 걸쳐서 작성하거나 포매팅을 하기 위해서 사용합니다.

태그드 템플릿 리터럴은 앞에 나와있는 태그 함수를 호출하여 결과를 리턴합니다.
여기에서 태그 함수의 파라미터는 expression으로 구분된 문자열 배열과 expression이 순서대로 들어가게 됩니다.

좀 더 쉬운 이해를 위해 아래 예제 코드를 봅시다.

const name = '인제';
const region = '서울';

function myTagFunction(strings, nameExp, regionExp) {
  let str0 = strings[0]; // "제 이름은 "
  let str1 = strings[1]; // "이고, 사는 곳은"
  let str2 = strings[2]; // "입니다."

  // 여기에서도 template literal을 사용하여 리턴할 수 있음
  return `${str0}${nameExp}${str1}${regionExp}${str2}`;
}

const output = myTagFunction`제 이름은 ${name}이고, 사는 곳은${region}입니다.`;

// 출력 결과
// 제 이름은 인제이고, 사는 곳은 서울입니다.
console.log(output);

위 코드는 태그드 템플릿 리터럴을 사용한 예제입니다.
태그 함수에 파라미터가 어떻게 들어가는지 쉽게 파악되죠?

이처럼 태그드 템플릿 리터럴을 사용하면 문자열과 expression을 태그 함수의 파라미터를 넣어
호출한 결과를 받게 됩니다.


styled-components
태그드 템플릿 리터럴을 사용하여 CSS속성이 적용된 리액트 컴포넌트를 만들어 줍니다.

styled-components를 사용하는 기본적인 방법은
아래와 같이 backticks(`)로 둘러싸인 문자열 부분에 CSS속성을 넣고
태그 함수 위치에는 styled.<HTML 태그> 형태로 사용합니다.
이렇게 하면 해당 HTML 태그에 CSS 속성들이 적용된 형태의 리액트 컴포넌트가 만들어집니다.

import React from "react";
import styled from "styled-components";

const Wrapper = styled.div`
  padding: 1em;
  background: grey;  
`;

styled-components의 props 사용하기

styled-components에서 조건이나 동적으로 변하는 값을 사용해서 스타일링할 수 있는 방법은
바로 props입니다.
리액트 컴포넌트의 props와 같은 개념으로 이해하면 됩니다.

import React from "react";
import styled from "styled-components";

const Button = styled.button`
  color: ${props => props.dark ? "white" : "dark"},
  background: ${props => props.dark ? "black" : "white"};
  border: 1px solid black;
`;

function Sample(props) {
  return (
    <div>
      <Button>Normal</Button>
      <Button dark>Dark</Button>
    </div>
  )
}

export default Sample;

위의 Button이라는 컴포넌트는 styled-components를 사용해서 만들어진 것입니다.
그리고 styled-components를 사용하는 부분의 CSS속성을 보면 내부에 props가 사용된 것을 볼 수 있습니다.
여기에서는 props는 해당 컴포넌트에 사용된 props를 의미합니다.
따라서 실제 Button 컴포넌트를 사용하는 부분의 코드를 보면
<Button>Dark<Button>처럼 props로 dark를 넣어 주는 것을 볼 수 있습니다.
그리고 이렇게 들어간 props는 그대로 styled-components로 전달됩니다.

이 기능을 사용하면 styled-components를 사용하여 다양한 스타일을 자유자재로 구현할 수 있습니다.

styled-components의 스타일 확장하기

앞에서 styled-components를 사용하면 리액트 컴포넌트가 생성된다고 설명했습니다.
그렇다면 이렇게 생성된 컴포넌트를 기반으로 추가적인 스타일을 적용하고 싶을 경우에는 어떻게 해야할까요?
styled-components에서는 이를 위한 스타일 확장 기능을 제공합니다.

import React from "react";
import styled from "styled-components";

// Button 컴포넌트
const Button = styled.button`
  color: grey;
  border: 1px solid black;
`;

// Button에 style이 추가된 RoundedButton 컴포넌트
const RoundedButton = styled(Button)`
  border-radius: 16px;
`;

function Sample(props) {
  return (
    <div>
      <Button>Normal</Button>
      <RoundedButton>Rounded</RoundedButton>
    </div>
  )
}

export default Sample;

먼저 Button 컴포넌트는 HTML의 button 태그를 기반으로 만들어진 단순한 버튼입니다.
그리고 RoundedButton 컴포넌트를 만드는 부분을 보면 HTML 태그가 빠져있고
Button 컴포넌트가 괄호로 둘러싸인 채로 들어가 있는 것을 볼 수 있습니다.
이것이 바로 다른 컴포넌트의 스타일을 확장해서 사용하는 부분입니다.

(실습) styled-components를 사용하여 스타일링해 보기

Blocks.jsx

import styled from "styled-components";

const Wrapper = styled.div`
    padding: 1rem;
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    justify-content: flex-start;
    background-color: lightgrey;
`;

const Block = styled.div`
    padding: ${(props) => props.padding};
    border: 1px solid black;
    border-radius: 1rem;
    background-color: ${(props) => props.backgroundColor};
    color: white;
    font-size: 2rem;
    font-wright: bold;
    text-align: center;
`;

const blockItems = [
    {
        label: "1",
        padding: "1rem",
        backgroundColor: "red"
    },
    {
        label: "2",
        padding: "3rem",
        backgroundColor: "green"
    },
    {
        label: "3",
        padding: "2rem",
        backgroundColor: "blue"
    }
];

function Blocks(props) {
    return (
        <Wrapper>
            {blockItems.map((blockItem) => {
                return (
                    <Block
                        padding={blockItem.padding}
                        backgroundColor={blockItem.backgroundColor}
                    >
                        {blockItem.label}
                    </Block>    
                );
            })}
        </Wrapper>
    );
}

export default Blocks;

index.js

수정 후 브라우저를 확인하면 아래 그림처럼 세 개의 박스가 가로로 나열되어 나타난다.
이것은 현재 flex-direction이 row로 되어 있기 때문입니다.

align-items 속성을 baseline으로 변경.

align-items 속성을 flex-end 변경.

alifn-items 속성을 stretch로 바꾸면 아래와 같이 박스가 세로로 늘어나는 것을 확인할 수 있습니다.

이번에는 박스들을 세로로 정렬해 봅시다.
flex-direction 속성을 column으로 변경하면 됩니다.

flex-direction 속성을 column-reverse로 변경

요약

CSS

  1. CSS란?

    • Cascading Style Sheets의 약자로 스타일링을 위한 언어
    • 하나의 스타일이 여러 개의 엘리먼트에 적용될 수 있고,
      하나의 엘리먼트에도 여러 개의 스타일이 적용될 수 있음
  2. 선택자(selector)

    • 스타일을 어떤 엘리먼트에 적용할지 선택하게 해주는 것
    • 엘리먼트 선택자
      - HTML 태그의 이름으로 엘리먼트를 선택
    • id 선택자
      - 엘리먼트의 id 속성으로 엘리먼트를 선택
      - 샾(#) 뒤에 아이디를 넣어서 사용
    • 클래스 선택자
      - 엘리머느의 클래스 속성으로 엘리먼트를 선택
      - 점(.) 뒤에 클래스명을 넣어서 사용
    • 전체 선택자
      - 전체 엘리먼트에 적용하기 위한 선택자
      - Asterisk(*)를 사용
    • 그룹 선택자
      - 여러 가지 선택자를 그룹으로 묶어 하나의 스타일을 적용하기 위해 사용하는 선택자
      - 각 선택자를 콤마(,)로 구분하여 적용
    • 엘리먼트의 상태와 관련된 선택자
      - 엘리먼트의 다양한 상태에 따라 스타일을 적용하기 위한 선택자
      - :hover, :active, :focus, :checked, :first-child, :last-child
  3. CSS 문법과 선택자

    • 선택자와 스타일로 구성됨
    • 선택자를 먼저 쓰고 이후에 적용할 스타일을 중괄호 안에 세미콜론(;)으로 구분하여 하나씩 기술
    • 각 스타일은 CSS 속성과 값으로 이뤄진 키-값 쌍이며, CSS 속성의 이름과 값을 콜론( : )으로 구분
  4. 레이아웃과 관련된 속성

    • 레이아웃은 화면에 엘리먼트들을 어떻게 배치할 것인지를 의미
    • display : 엘리먼트를 어떻게 표시할지 그 방법에 관한 속성
    • visibility : 엘리먼트를 화면에 보여주거나 감추기 위한 속성
    • position : 엘리먼트를 어떻게 위치시킬 것인지 정의하기 위한 속성
    • width/height : 가로/세로 길이를 정의하기 위한 속성
    • min-width/min-height : 최소 가로/세로 길이를 정의하기 위한 속성
    • max-width/max-height : 최대 가로/세로 길이를 정의하기 위한 속성
  5. 플렉스박스

    • 기존 CSS의 레이아웃 사용의 불편한 부분을 개선하기 위해 등장
    • 플렉스 컨테이너와 플렉스 아이템으로 구성되며 컨테이너는 여러 개의 아이템을 포함
    • 컨테이너의 플렉스와 관련된 CSS 속성은 아이템들을 어떤 방향과 어떤 수서로 배치할 것인지를 정의
    • flex-direction : 아이템들이 어떤 방향으로 배치될 것인지를 지정하기 위한 속성
      - main axis : flex-direction으로 지정된 방향으로 향하는 축
      - cross axis : main axis를 가로지르는 방향으로 향하는 축
    • aling-items
      - 컨테이너 내에서 아이템을 어떻게 정렬할 것인지를 결정하기 위한 속성
      • cross axis를 기준으로 함
    • justify-content
      - 컨테이너 내에서 아이템을 어떻게 나란히 맞출 것인지를 결정하기 위한 속성
      - main axis를 기준으로 함
  6. 폰트와 관련된 속성

    • font-family
      - 어떤 글꼴을 사용할 것인지를 결정하는 속성
      - 지정한 글꼴을 찾지 못했을 경우를 대비해서 사용할 글꼴을 순서대로 지정해 줘야 함
    • font-size : 글꼴의 크기와 관련된 속성
    • font-weight : 글꼴의 두께와 관련된 속성
    • font-style : 글꼴의 스타일을 지정하기 위한 속성
  7. 많이 사용하는 기타 속성

    • background-color : 엘리먼트의 배경색을 지정하기 위한 속성
    • border : 엘리먼트에 테두리를 넣기 위한 속성

styled-components

  1. CSS 문법을 그대로 사용하면서 결과물을 스타일링된 컴포넌트 형태로 만들어주는 오픈소스 라이브러리

  2. 컴포넌트 개념을 사용하기 때문에 리액트와 궁합이 잘 맞음

  3. 태그드 템플릿 리터럴을 사용하여 구성 요소의 스타일을 지정

0개의 댓글