[React] Styled Components

문지은·2023년 7월 29일
1

React

목록 보기
14/24
post-thumbnail

CSS

CSS

  • Cascading Style Sheets
  • 하나의 스타일이 여러 개의 엘리먼트에 적용될 수 있고, 하나의 엘리먼트에도 여러 개의 스타일이 적용될 수 있음

CSS 문법과 선택자

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

선택자(Selector)

  • 스타일을 어떤 엘리먼트에 적용할지 선택하게 해주는 것

선택자 유형

  • 엘리먼트 선택자
    • HTML 태그의 이름으로 엘리먼트를 선택
h1 {
  color: green;
}
  • id 선택자
    • 엘리먼트의 id 속성으로 엘리먼트를 선택
    • # 뒤에 아이디를 넣어 사용
#section {
	background-color: black;
}
  • 클래스 선택자
    • 엘리먼트의 클래스 속성으로 엘리먼트를 선택
    • . 뒤에 클래스명을 넣어서 사용
    • 특정 HTML 태그에 클래스가 있는 경우에 스타일을 적용하고 싶으면 HTML 태그명 뒤에 점을 찍고 클래스 이름을 넣어주면 됨
.medium {
	font-size: 20px;
}

p.medium {
	font-size: 20px;
}
  • 전체 선택자
    • 전체 엘리먼트에 적용하기 위한 선택자
    • 한국에서는 흔히 별표라고 부르는 Asterisk(*) 사용
* {
	font-size: 20px;
    color: blue;
}
  • 그룹 선택자
    • 여러 가지 선택자를 그룹으로 묶어 하나의 스타일을 적용하기 위해 사용하는 선택자
    • 각 선택자를 콤마(,)로 구분하여 적용
h1, h2, p {
	color: black;
    text-align: center;
}

엘리먼트의 상태와 관련된 선택자

  • 엘리먼트의 다양한 상태에 따라 스타일을 적용하기 위한 선택자
  • :hover
    • 마우스 커서가 엘리먼트 위에 올라왔을 때
  • :active
    • 주로 <a> 태그에 사용, 엘리먼트가 클릭됐을 때
  • :focus
    • 주로 <input> 태그에 사용, 엘리먼트가 초점을 갖고 있을 경우
  • :checked
    • radio button이나 checkbox 같은 유형의 <input> 태그가 체크되어 있는 경우
  • :first-child, last-child
    • 상위 엘리먼트를 기준으로 각각 첫 번째 child, 마지막 child일 경우
button:hover {
	font-weight: bold;
}

a:active {
	color: red;
}

input:focus {
	color: #000000;
}

option:checked {
	background: #00ff00;
}

p:first-child {
	background: #ff0000;
}

p:last-child {
	background: #0000ff;
}

레이아웃과 관련된 속성

  • 화면에 엘리먼트를 어떻게 배치할 것인지 결정

display

  • 엘리먼트를 어떻게 표시할지에 관한 속성
div {
	display: none | block | inline | flex;
}
  • display: none;
    • 엘리먼트를 화면에서 숨기기 위해 사용
    • 엘리먼트가 삭제되는 것이 아니라 존재하긴 하지만 화면에 보이지 않는 것
    • <script> 태그의 display 속성 기본 값은 display: none;
  • display: block;
    • 블록 단위로 엘리먼트를 배치하는 것
    • 엘리먼트가 새로운 줄에서 시작하여 위치한 곳 전체의 width를 차지
    • <p>, <div>, <h1> ~ <h6> 태그의 display 속성 기본 값은 display: block;
  • display: inline;
    • 엘리먼트를 라인 안에 넣는 것
    • <span> 태그의 display 속성 기본 값은 display: inline;
    • 이 속성을 사용하게 되면 모든 width, height과 관련된 속성들은 효과가 없어짐
  • display: flex;
    • 엘리면트를 블록 레벨의 플렉스 컨테이너로 표시하는 것
    • 컨테이너이기 때문에 내부에 다른 엘리먼트들을 포함한다고 생각하면 됨

visibility

  • 눈에 잘 보이는 성질
div {
	visibility: visible | hidden;
}
  • visibility: visible;
    • 엘리먼트를 화면에 보이게 함
  • visibility: hidden;
    • 엘리먼트를 화면에 안보이게 감춤
    • 화면에서 영역은 그대로 차지

position

  • 엘리면트를 어떻게 위치시킬 것인지 정의
div {
	position: static | fixed | relative | absolute;
}
  • position: static;
    • 기본 값으로 엘리먼트를 원래의 순서대로 위치
  • position: fixed;
    • 엘리먼트를 브라우저 window에 상대적으로 위치
  • position: relative;
    • 엘리먼트를 보통의 위치에 상대적으로 위치시킴
  • position: absolute;
    • 엘리먼트를 절대 위치에 위치 이떄 기준은 첫 번째 상위 엘리먼트가 됨

Flexbox

  • 기존 CSS의 레이아웃 사용의 불편한 부분을 개선하기 위해 등장
  • 플렉스 컨테이너와 플렉스 아이템으로 구성되며 컨테이너는 여러 개의 아이템을 포함
  • 컨테이너의 플렉스와 관련된 CSS 속성은 아이템들을 어떤 방향과 어떤 순서로 배치할 것인지를 정의
  • display:flex; 를 써서 엘리먼트를 플렉스 컨테이너로 사용
div {
	display: flex;
    flex-direction: row | column | row-reverse | column-reverse;
    align-items: stretch | flex-start | center | flex-end | baseline;
    justify-content: flex-start | cnetner | flex-end | space-between | space-around;
}

flex-direction

  • 아이템이 어떤 방향으로 배치될 것인지를 지정
  • row
    • 기본 값이며 아이템을 행을 따라 가로 순서대로 왼쪽부터 배치
  • column
    • 아이템을 열을 따라 세로 순서대로 위쪽부터 배치
  • row-reverse
    • 아이템을 행의 역방향으로 오른쪽부터 배치
  • column-reverse
    • 아이템을 열의 역방향으로 아래쪽부터 배치

main axis 와 cross axis

  • main axis
    • flex-direction으로 지정된 방향으로 향하는 축
  • cross axis
    • main axis를 가로지는 방향으로 향하는 축

align-items

  • cross axis 기준으로 컨테이너 안에서 아이템을 어떻게 정렬할 것인지를 결정
  • stretch
    • 기본 값으로써 아이템을 늘려서 컨테이너를 가득 채움
  • flex-start
    • cross axis의 시작 지점으로 아이템을 정렬
  • center
    • cross axis의 중앙으로 아이템을 정렬
  • flex-end
    • cross axis의 끝 지점으로 아이템을 정렬
  • baseline
    • 아이템을 baseline 기준으로 정렬

justify-content

  • 컨테이너 안에서 아이템들을 main axis를 기준으로 어떻게 나란히 맞출 것인지를 결정
  • flex-start
    • main axis의 시작 지점으로 아이템을 맞춤
  • center
    • main axis의 중앙으로 아이템을 맞춤
  • flex-end
    • main axis의 끝 지점으로 아이템을 맞춤
  • space-between
    • main axis를 기준으로 첫 아이템은 시작 지점에 맞추고 마지막 아이템은 끝 지점에 맞추며, 중간에 있는 아이템들 사이의 간격이 일정하게 되도록 맞춤
  • space-around
    • main axis를 기준으로 각 아이템의 주변 간격을 동일하게 맞춤
    • 여기에서 주변의 의미는 아이템의 시작과 끝을 의미

폰트와 관련된 속성

#title {
	font-family: "사용할 글꼴 이름", <일반적인 글꼴 분류>;
    font-size: value;
    font-weight: normal | bold;
    font-style: normal | italic | oblique;
}

font-family

  • 어떤 글꼴을 사용할 것인지를 결정하는 속성
  • 지정한 글꼴을 찾지 못했을 경우를 대비해서 사용할 글꼴들을 순서대로 지정해 줘야 함
  • 일반적인 글꼴 분류
    • serif
      • 각 글자의 모서리에 작은 테두리에 갖고 있는 형태의 글꼴
    • sans-serif
      • 모서리에 테두리가 없이 깔끔한 선을 가진 글꼴이며 컴퓨터 모니터에는 serif보다 가독성이 좋음
    • monospace
      • 모든 글자가 같은 가로 길이를 가지는 글꼴, 코딩을 할때 주로 사용
    • cursive
      • 사람이 쓴 손글씨 모양의 글꼴
    • fantasy
      • 장식이 들어간 형태의 글꼴

font-size

  • 글꼴의 크기와 관련된 속성
  • px, em, rem, vw 등의 단위를 사용 가능
    • 1em은 16px과 동일

font-weight

  • 글꼴의 두께와 관련된 속성
  • normal, bold를 사용하거나 100 ~ 900 까지 100 단위의 숫자로 된 값 사용
    • 숫자가 클 수록 글자의 두께가 두꺼워짐

font-style

  • 글꼴의 스타일을 지정하기 위한 속성
  • normal
    • 일반적인 글자의 형태
  • italic
    • 글자가 기울어진 형태로 나타남
    • 해당 글꼴이 italic을 지원하는지를 확인하고 사용해야 함
  • oblique
    • 글자가 비스듬한 형태로 나타남

Styled-components

styled-components 설치하기

  • 아래 명령어를 통해 최신 버전의 style-components 설치
# npm을 사용하는 경우
npm install --save styled-components

# yarn을 사용하는 경우
yarn add styled-components
  • 간단한 컴포넌트를 하나 만들어 작동 확인
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;

styled-components 기본 사용법

  • style-componenets는 tagged template literal을 사용하여 구성요소의 스타일을 지정

template literal

  • literal을 템플릿 형태로 사용하는 자바스크립트의 문법
  • backticks(`)를 사용하여 문자열을 작성하고 그 안에 대체 가능한 expression을 넣는 방법
  • untagged template literal과 tagged template literal로 나뉨

untagged template literal

  • 보통 문자열을 여러 줄에 걸쳐서 작성하거나 formatting을 하기 위해 사용
// 단순한 문자열
`string text`

// 여러 줄에 걸친 문자열
`string text line 1
string text line 2`

// 대체 가능한 expression이 들어있는 문자열
`string text ${expression} string text`

tagged template literal

  • tag function를 호출하여 결과 리턴
  • tag 함수의 파라미터는 expression으로 구분된 문자열 배열과 expression이 순서대로 들어가게 됨
// myFuntion의 파라미터로 expression으로 구분된 문자열 배열과 expression이 순서대로 들어간 형태로 호출됨
myFunction`string text ${expression} string text`
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)

styled-components

  • styled-components는 tagged template literal을 사용하여 CSS 속성이 적용된 리액트 컴포넌트를 만들어줌
  • 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 값에 따라 styled-componenets를 사용하여 다양한 스타일을 구현할 수 있음.
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;
  • 실행 결과

styled-components의 스타일 확장하기

  • styled-components를 사용하여 생성된 컴포넌트를 기반으로 추가적인 스타일을 적용할 수 있음
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;
`;

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

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

export default Sample;
  • 실행 결과

실습

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-weight: 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;
  • 실행 결과

실습 전체 코드

References

profile
코드로 꿈을 펼치는 개발자의 이야기, 노력과 열정이 가득한 곳 🌈

0개의 댓글