React 가이드 4편 - Component Styling

kdeun1·2022년 11월 3일
0

React 정리

목록 보기
4/7

앱이 보기좋게 컴포넌트를 스타일링한다. 조건부나 동적인 방식으로 스타일링을 하는 다양한 기술들이 존재한다.

  • Styled Components : 인기있는 서드파티 라이브러리. 고유한 범위를 가진 스타일로 미리 스타일이 지정된 컴포넌트를 설정할 수 있다.
  • CSS Modules

동적 스타일

동적 인라인 스타일

일반적인 css 파일을 js파일에 import하여 사용하지만, 해당 컴포넌트가 아닌 전체 페이지의 모든 요소에 영향을 미친다.

<label style={{ color: isValid ? 'black' : 'red' }}>Contents</label>

이런 방식은 문제가 존재한다. 항상 inline 방식이어야 하며, css를 오버라이드하는 최우선 순위로 적용되기 때문이다.

Vue의 Binding Inline Style과 동일한 방식이다.

<div :style="{ color: isValid ? 'black' : 'red' }">Contents</div>

동적 css 클래스

백틱을 사용한 템플릿 리터럴을 이용하여 상태 값에 동적으로 클래스명을 구현한다.

<div className={`form-control ${!isValid ? 'invalid' : ''}`}>
  // ...
</div>

Vue의 Binding HTML Classes와 동일한 방식이다.

<div :class="[isActive ? activeClass : '', errorClass]">Contents</div>

Styled Components

컴포넌트 파일에 css파일을 import하면, 컴포넌트에만 적용되는 것이 아니라 앱 페이지 전체에 삽입된다. 그렇다면 앱 내 동일한 클래스명에 다같이 적용된다는 뜻을 의미한다. 대규모 프로젝트에서는 실수할 수 있는 잠재적 사이드이펙트를 가질 수 있다.
styled components는 특정 스타일이 첨부된 컴포넌트를 구축할 수 있도록 도와주는 패키지이다. 특정 컴포넌트를 제외한 다른 컴포넌트에는 영향을 주지 않는다.

npm install --save styled-components

styled-components를 설치한다.

import styled from 'styled-components';

const Button = styled.button`
  font: inherit;
  color: white;
  
  &:focus {
  	outline: none;
  }
  
  &:hover {
  	background: #ac0e77;
  }
`;

export default Button;

styled.button뒤에 백틱이 존재한다. 이를 taged template literal이라고 한다. styled.button 함수에 특별한 방식으로 메소드에 값을 전달한다. styled. 뒤에는 요소들을 넣을 수 있다. 그 중 Button 컴포넌트를 리턴하기 위해 button을 선택하였다. 백틱 안에 css의 내용을 추가한다. 그리고 & 연산자를 사용하여 focur, hover, active 등의 상태 스타일도 추가한다.

devtools의 elements탭에서 button 요소를 살펴보자

<button type="submit" class="sc-bcXHqe iSZPmF">Add</button>

class에 이상한 문자열 2개가 존재한다. 이 클래스명은 유저가 만든 것이 아닌 styled-components 패키지에 의해 동적으로 생성된 문자열이다. 이 패키지는 우리가 백틱 안에 설정한 스타일을 보고 생성된 임의의 클래스명으로 스타일을 감싼다. 고유한 임의의 클래스명으로 생성하여 다른 컴포넌트에 영향을 주지 않게 만든다.

Vue의 Scoped CSS와 동일한 방식이다.

<style scoped>
.example {
  color: red;
}
</style>
<template>
  <div class="example">hi</div>
</template>

Styled Components에서의 props 값 처리

props를 이용하여 동적 스타일을 구현할 수 있다.

const FormDiv = styled.div`
  color: white;
  
  &.invalid {
    color: red;
  }
`;

return (
  <FormDiv className={!isValid && 'invalid'}>
    // ...
  </FormDiv>
);

styled components로 만들어진 컴포넌트를 JSX안에 넣고 className를 동적으로 구성하는 방법이 존재한다.

const FormDiv = styled.div`
  color: white;
  
  &.invalid {
    color: ${props => (props.invalid ? 'red' : 'white')};
  }
`;

return (
  <FormDiv invalid={!isValid}>
    // ...
  </FormDiv>
);

invalid를 태그에 바인딩시키고, styled안에 props로 활용할 수 있다. 또한 가상선택자 스타일을 제거할 수 있다.

Vue의 v-bind() in CSS와 비슷한 것 같다.

<template>
  <div class="text">hello</div>
</template>
<script>
export default {
  data() {
    return {
      color: 'red'
    }
  }
}
</script>
<style>
.text {
  color: v-bind(color);
}
</style>

Styled Components + media query

import styled from 'styled-components';

const Button = styled.button`
    @media (조건) {
    	...
    }
`;

CSS Module

css 파일과 js를 분리하는 것을 선호할 때 사용.
브라우저에서 코드가 실행되기 전에 코드의 변환이 필요하다. react CRA에는 이미 css 모듈을 지원하도록 설정되어있다.

스타일을 담은 Buttom.module.css 파일을 생성한다.

import styles from './Button.module.css';

const Button = props => {
  return (
    <button
      type={props.type}
      className={styles.button}
      onClick={props.onClick}
    >
      {props.children}
    </button>
  );
};

export default Button;

DevTools > elements에

<button type="submit" class="Button_button__nN4lI">Add</button>

와 같이 이상한 클래스명이 존재한다. 실제 styled 컴포넌트가 추가한 이름이 아니다.
컴포넌트명_클래스명__고유해시값으로 클래스명이 만들어진다.
css 클래스나 파일을 가지고 클래스명을 고유하게 변경한다. 새로운 클래스명으로 래핑한다.

css 모듈의 개념은 css 파일에서 설정한 스타일의 범위가 import하는 컴포넌트에만 한정된다.

css modules + dynamic style

.form-control {
  background-color: red;
}
.form-control.invalid {
  background-color: red;
}
import styles from './CourseInput.module.css';

const Form = () => {
  return (
    <form>
      <div className={`${styles['form-control']} ${!invalid && styles.invalid}`}>
    </form>
  );
}

객체로서 className에 동적으로 접근 가능


참고

profile
프론트엔드 개발자입니다.

0개의 댓글