공부/React

[React] 컴포넌트 스타일링

hyunh404 2024. 1. 24. 04:03
728x90

 

컴포넌트와 마찬가지로 css 또한 파일을 분리하여 저장하는 것이 좋다.

관련한 css파일을 만들어주고 import를 이용해 스타일을 적용해준다.

 

바닐라 css

 

장점

1. css 파일을 import 하면 적용가능하며, 다른사람도 파일을 받아 작업하는 것이 가능하다.
2. css를 직접 작업할 수 있다. 모든 것은 작업하는 사람에게 달려있는 것이다. 

 

단점

1. css를 알아야한다.
2. 다른 컴포넌트 간 css 충돌이 발생할 수 있다.

 

2번의 의미는 css가 원하는 컴포넌트로 스코핑되지 않을 수 있다는 것이다.

지정한 클래스나 id에 해당하는 모든 파일의 코드에 css가 적용된다는 것이다.

따라서 이는 크게 문제가 되지 않지만, 특정한 css만 적용하고 싶다면 inline css를 통해 해결할 수 있다.

 

 

inline css

 

리액트 앱의 jsx 파일에서 스타일 속성을 지정하려면 style={ { } } 형태의 코드를 사용해야한다.

 

장점

1. 빠르고 쉽게 원하는 css를 적용할 수 있다.
2. 지정한 요소 이외의 다른 요소에는 적용되지 않는다.
3. 동적 스타일링이 간단하다.

 

단점

1. 모든 요소를 개별적으로 스타일링 해야한다.
2. css코드와 jsx코드 구분이 없다.

 

 

동적 및 조건적 inline css

 

조건에 따라 스타일을 변경하고 싶다면 클래스이름을 통해 지정할 수 있다.

 

먼저, 동적인 스타일링은 인라인 스타일링을 통해 간단히 할 수 있다.

다음과 같이 스타일을 지정하여 원하는 요소의 배경색을 스타일링할 수 있다.

style={{
            backgroundColor: emailNotValid ? '#fed2d2' : '#d1d5db'
          }}

 

 

그러나 인라인 스타일링은 종종 중복이 발생하고 모든 css코드가 jsx코드에 들어가게 되어 이상적이지 못하다는 단점이 있다.

따라서 별도의 css파일을 이용해 조건적으로 스타일링을 해야한다.

클래스 이름을 추가하여 스타일링을 시작한다.

 

또한, 동적인 스타일링을 적용하려 할 수도 있다.

그러면 className을 지정하고 백틱( ` ` )을 이용하여 동적인 스타일링은 지정할 수 있다.

이 방법으로 문자열을 만들 때, 특수한 자바스크립트 구문인 ${ ` ` }를 활용하여 하드코딩된 값과 동적으로 삽입된 값이 포함된 문자열을 만들 수 있게 한다.

className={`label ${emailNotValid ? "invalid" : ""}`}

 

 

css모듈로 css규칙 스코핑

 

위와 같이 조건적으로 css를 적용하는 것은 간단하다.

그러나 css코드와 css규칙이 컴포넌트에 스코핑되어 있지 않고, css코드를 실수로 작성할 수 있다는 단점이 존재한다.

또한 정의된 컴포넌트 이외의 다른 컴포넌트에 적용되지 않길 원하면 css모듈을 사용하여 달성할 수 있다.

 

css모듈은 빌드도구가 css클래스 이름을 변환하고 파일 당 고유한 것으로 보장되는 클래스 이름만 사용하는 방식이다.

이는 다음과 같이 코드를 작성해줄 수 있다.

따라서 최종적으로 이 빌드과정은 클래스 스타일이 가져온 컴포넌트 파일로 스코핑 되도록 보장한다.

import classes from "./Header.module.css";
 
<p className={classes.paragraph}>
        A community of artists and art-lovers.
</p>

 

 

장점

1. css코드가 jsx코드와 독립되어 있다.
2. css코드를 알고 있는대로 작성하고 다른사람이 편집하는 것도 가능하다.
3. css 클래스와 그것을 사용하는 규칙이 해당 규칙을 가져온 css파일을 포함하는 컴포넌트 파일로 스코프된다.

 

단점

1. 여전히 css를 알아야한다.
2. 사용할 때 상대적으로 작고 많은 css파일을 마주하게 될 수 있다.

 

 

Styled Components

 

이는 css규칙이나 스타일을 별도의 파일이나 인라인으로 정의하지 않고 해당 패키지의 도움을 받아 생성된 특별한 컴포넌트 내에서 스타일을 정의하는 것이다.

따라서 먼저 패키지를 설치해주어야한다.

 

패키지를 적용하기 위해 import해준다.

import { styled } from "styled-components";

 

 

이제 예를들어,

div요소를 스타일링하려고 하면 styled를 사용하여 설정할 수 있다. 이때도 백틱을 사용해야한다.

또한 여러 코드를 작성할 수 있다는 장점이 있다.

 

또한 이름을 지정하여 커스텀 컴포넌트를 만들 수 있다.

const ControlContainer = styled.div`
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 1.5rem;
`;

 

따라서 div를 새롭게 지정한 커스텀 컴포넌트인 ControlContainer를 사용하여 교체해줄 수 있다.

<ControlContainer>
         <p className="paragraph">
          <Label
            className={`label ${emailNotValid ? "invalid" : ""}`}
          >
            Email
          </Label>
          <Input
            $invalid={emailNotValid}
            type="email"
            className={emailNotValid ? "invalid" : undefined}
            onChange={(event) => handleInputChange("email", event.target.value)}
          />
        </p>
         <p>
          <Label
            className={`label ${emailNotValid ? "invalid" : ""}`}
          >
            Password
          </Label>
          <Input
            $invalid={passwordNotValid}
            type="password"
            className={passwordNotValid ? "invalid" : undefined}
            onChange={(event) =>
              handleInputChange("password", event.target.value)
            }
          />
        </p>
      </ControlContainer>

 

 

그러나 이는 일부 스타일이 사라져 있는 것이다. 일부 스타일만 적용했기 때문이다.

따라서 styled components를 이용해 유동적 컴포넌트를 생성한다.

 

예를들어,

위의 input에 대한 내용을 styled components 이용해 간편하게 이동시킬 수 있다.

새로운 상수를 정의하여 스타일을 지정해주면 내장된 label, input를 대체하여 Label이나 Input요소로 사용가능하다.

따라서 이제 type과 같은 속성에 대해 수정하지 않아도 검증이 정상적으로 작동한다.

 

 

 

728x90

 

 

styled components 동적 및 조건적 스타일링

 

현재 여전히 바닐라 css와 혼용하여 코드를 작성하고 있기 때문에 동적 및 조건적 스타일링을 할때에도 styled components를 활용해 하나의 솔루션만 이용하고 싶다.

styled components는 ${ () => }와 같이 함수를 정의하여 동적으로 스타일링할 수 있다.

color: ${({ $invalid }) => ($invalid ? "#f87171" : "#6b7280")};

 

조건적 스타일링도 동일한 방법으로 설정해줄 수 있다.

background-color: ${({ $invalid }) => ($invalid ? "#fed2d2" : "#d1d5db")};
  color: ${({ $invalid }) => ($invalid ? "#ef4444" : "#374151")};
  border: 1px solid ${({ $invalid }) => ($invalid ? "#f73f3f" : "transparent")};

 

또한 invalid이름을 사용할 때에는 내장 요소와 혼동되지 않게끔 차별점을 두기 위해 $를 사용해줘야한다.

<Label $invalid={invalid}>{label}</Label>
<Input $invalid={invalid} {...props} />

 

 

styled components : 가상 선택자, 중첩 규칙, 미디어 쿼리

 

@media (min-width: 768px) {
  header {
    margin-bottom: 4rem;
  }

  header h1 {
    font-size: 2.25rem;
  }
}

 

위와 같은 미디어 쿼리나 중첩된 코드를 styled components로 설정해보려 한다.

이는 지정하고 싶은 스타일에 해당하는 모든 코드를 옮기고 예를들어, header에 관한 스타일이라면 옮긴 코드에서 header의 하위 요소에는 header 대신 &기호를 사용해주면 된다.

& : 규칙들이 헤더 내의 어느 요소에나 영향을 미친다는 것을 보여준다.

 

const StyleHeader = styled.header`
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-top: 2rem;
  margin-bottom: 2rem;

  & img {
    object-fit: contain;
    margin-bottom: 2rem;
    width: 11rem;
    height: 11rem;
  }

  & h1 {
    font-size: 1.5rem;
    font-weight: 600;
    letter-spacing: 0.4em;
    text-align: center;
    text-transform: uppercase;
    color: #9a3412;
    font-family: "Pacifico", cursive;
    margin: 0;
  }

  & p {
    text-align: center;
    color: #a39191;
    margin: 0;
  }

  @media (min-width: 768px) {
    margin-bottom: 4rem;

    & h1 {
      font-size: 2.25rem;
    }
  }
`;

 

 

재사용 가능 컴포넌트 생성, 조합

 

스타일을 지정할 때 동일한 스타일을 가진 동일한 컴포넌트가 다른 부분에서 필요할 가능성도 존재한다.

따라서 별도의 파일을 만들어 스타일과 요소를 export하고 import를 통해 컴포넌트를 활용해준다.

 

분리된 파일에서 속성값을 받기 위해 받는 속성 이름과 동일한 요소를 받을 파일에도 추가해주어야 한다.

이는 기본 입력으로 분리된 컴포넌트에 전달될 것이다.

label="Email"

 

 

따라서 이제 컴포넌트를 재사용할 수 있기에 일반적인 css를 추가하는 것도 가능하다.

 

 

다음은 css를 적용하려 간단히 만든 페이지이다.

기본 구조는 주어진 틀을 사용하였다.

간단한 예시 프로젝트

 

 

css 프로젝트

 

 

css 프로젝트를 만든 코드를 깃허브에 올려두었다.

https://github.com/BB545/-react-Components-Styling

728x90