리액트 컴포넌트 스타일링

김지영·2022년 6월 25일
0

React-study

목록 보기
4/5

동적 인라인 스타일 설정하기

  • 만약 사용자가 아무것도 작성하지 않거나 공백만 작성했을 때 제출버튼을 누르면 label과 입력창의 색을 빨간색으로 보이게 하고싶다.

    • <label style={{ color: !isValid ? 'red' : 'black' }}>Course Goal</label>
      <input
          type="text"
          onChange={goalInputChangeHandler}
          style={{ borderColor: !isValid ? 'red' : 'black', background: !isValid ? 'salmon' : 'transparent' }}
          />
    • 하지만 inline 요소로 style을 작성하면 기존에 css에 작성했던 style을 잡아먹어 버리는 단점이 있다.

동적으로 css 클래스 설정하기

  • label과 input을 감싸는 div 태그에 입력이 유효하지 않을 때만 invalid라는 클래스가 추가되도록 해보자.

  • css에서 .form-control.invalid라고 작성을 하면 form-control이 invalid 클래스에 접근 가능하다고 선언하는 것이다.

    • .form-control.invalid input {
        border-color: red;
        background: #ffd7d7;
      }
      
      .form-control.invalid label {
        color: red;
      }
  • div 태그의 class가 동적으로 설정되어야 하므로 중괄호로 설정하고, 백틱 안에 ${}를 써서 자바스크립트 표현식을 넣는다.

    • <div className={`form-control ${!isValid ? 'invalid' : ''}`}>
  • css가 import된 파일에서 뿐만 아니라 해당 클래스를 갖고 있다면 전체 페이지에 있는 모든 요소에 적용된다.

  • 해결방법

    1. styled components 패키지 사용
      • https://styled-components.com/
      • 특정 스타일이 첨부된 컴포넌트를 구축할 수 있도록 도와주는 패키지
      • 해당 컴포넌트를 제외한 다른 컴포넌트에는 영향을 미치지 않는다.
      • npm install --save styled-components

styled components

  • styled components 임포트

    • import styled from 'styled-components'
  • 태그드 템플릿 리터럴

    • const Button = styled.button``
    • 자바스크립트의 기본 기능

    • button이 styled 객체의 메소드이고, 괄호를 사용해서 호출하지 않고 백틱을 붙인다.

    • styled는 모든 html 요소에 대한 메소드를 갖고 있다.

    • 이것은 뒷단에서 메소드로 실행된다.

    • 백틱사이에 전달하는 것이 Button 메소드로 가고, button 메소드가 새로운 button 컴포넌트를 반환한다.

    • const Button = styled.button`
        font: inherit;
        padding: 0.5rem 1.5rem;
        border: 1px solid #8b005d;
        color: white;
        background: #8b005d;
        box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
        cursor: pointer;
      
        &:focus {
          outline: none;
        }
      
        &:hover,
        &:active {
          background: #ac0e77;
          border-color: #ac0e77;
          box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
        }
      `;
    • 이제 디폴트로 반환되는 button은 여기서 설정한 button 컴포넌트로 전달하는 모든 props를 적용한다.

    • 개발자 도구에 가면 처음보는 class가 두개 있는데, style-components 패키지에 의해 동적으로 생성된 클래스 이름이다.

    • 모든 클래스가 고유한 이름을 갖기 때문에 앱에 있는 다른 컴포넌트에 영향을 주지 않는다.

style components & 동적 props

  • 동적 props invalid를 가지는 div에 style components를 적용해보자.

  • styled 컴포넌트 함수에 의해 반환되는 컴포넌트가 그 아래 컴포넌트에 props를 전달한다.

  • 동적 props를 가지는 방법 1

    • invalid라는 클래스를 넣었다뺐다

    • const FormControl = styled.div`
        margin: 0.5rem 0;
      
        & label {
          font-weight: bold;
          display: block;
          margin-bottom: 0.5rem;
        }
      
        & input {
          display: block;
          width: 100%;
          border: 1px solid #ccc;
          font: inherit;
          line-height: 1.5rem;
          padding: 0 0.25rem;
        }
      
        & input:focus {
          outline: none;
          background: #fad0ec;
          border-color: #8b005d;
        }
      
        &.invalid input {
          border-color: red;
          background: #ffd7d7;
        }
      
        &.invalid label {
          color: red;
        }
      `;
      
      <FormControl className={!isValid && 'invalid'}>
  • 동적 props를 가지는 방법 2

    • invalid라는 속성을 보내주기

    • const FormControl = styled.div`
        margin: 0.5rem 0;
      
        & label {
          font-weight: bold;
          display: block;
          margin-bottom: 0.5rem;
          color: ${(props) => (props.invalid ? 'red' : 'black')};
        }
      
        & input {
          display: block;
          width: 100%;
          border: 1px solid ${(props) => (props.invalid ? 'red' : '#ccc')};
          background: ${(props) => (props.invalid ? '#ffd7d7' : 'transparent')};
          font: inherit;
          line-height: 1.5rem;
          padding: 0 0.25rem;
        }
      
        & input:focus {
          outline: none;
          background: #fad0ec;
          border-color: #8b005d;
        }
      `;
      
      <FormControl invalid={!isValid}>

style components & 미디어 쿼리

  • 작은 장치(화면)에서 버튼이 전체 너비를 차지하게 만들어보자.

  • const Button = styled.button`
      width: 100%;
      font: inherit;
      padding: 0.5rem 1.5rem;
      border: 1px solid #8b005d;
      color: white;
      background: #8b005d;
      box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
      cursor: pointer;
    
      @media (min-width: 768px) {
        width: auto;
      }
    
      &:focus {
        outline: none;
      }
    
      &:hover,
      &:active {
        background: #ac0e77;
        border-color: #ac0e77;
        box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
      }
    `;

CSS 모듈 사용하기

  • https://create-react-app.dev/docs/adding-a-css-modules-stylesheet/

  • css 파일에 이름을 지정해서 import한다.

    • css 파일 이름에 .module을 붙인다.

    • import styles from './Button.module.css';
  • styles는 객체이고 그 객체 안에 있는 클래스를 프로퍼티로 갖게 된다.

    • <button type={props.type} className={styles.button} onClick={props.onClick}>
    • 개발자 도구를 가보면 class 이름이 컴포넌트이름_클래스이름__고유한해시값으로 구성되어있다.

  • css 모듈은 모든 컴포넌트에 대해서 여기서 임포트하고 있는 모든 클래스의 이름을 바꿔 모든 css 파일을 고유하게 만든다.

  • css 모듈은 css 파일에서 설정한 css 스타일의 범위가 이 파일에 임포트하는 컴포넌트에 한정된다는 것을 확실하게 해준다.

CSS 모듈을 사용한 동적 스타일링

  • 프로퍼티 이름이 form-control이라서 유효하지 않다면 대괄호를 사용하고 작은 따옴표로 이름을 감싸준다.

    • <div className={styles['form-control']}>
  • 동적 클래스 추가

    1. 변환된 클래스 이름 입력

      • <div className={`${styles['form-control']}`}>
    2. 동적 클래스 입력

      • <div className={`${styles['form-control']} ${!isValid && styles.invalid}`}>
  • css 모듈에서 미디어 쿼리 설정

    • @media (min-width: 768px) {
        .button {
          width: auto;
        }
      }

완성 코드

0개의 댓글