Home 03-컴포넌트-스타일링
Post
Cancel

03-컴포넌트-스타일링

강의 링크


1. 동적 스타일

1) 동적 인라인 스타일

공백을 입력하면 테두리 색이 변하는 input 컴포넌트를 만들어보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import React, { useState } from 'react';

import Button from '../../UI/Button/Button';
import './CourseInput.css';

const CourseInput = props => {
  const [enteredValue, setEnteredValue] = useState('');
  const [isValid, setIsValid] = useState(true);

  const goalInputChangeHandler = event => {
    if (event.target.value.trim().length > 0) {
      setIsValid(true);
    }
    setEnteredValue(event.target.value);
  };

  const formSubmitHandler = event => {
    event.preventDefault();
    if (enteredValue.trim().length === 0) {
      setIsValid(false);
      return;
    }
    props.onAddGoal(enteredValue);
  };

  return (
    <form onSubmit={formSubmitHandler}>
      <div className="form-control">
         
        {/* state를 활용한 동적 인라인 스타일*/}
        <label style=>Course Goal</label>
        <input
          style=
          type="text"
          onChange={goalInputChangeHandler}
        />
      </div>
      <Button type="submit">Add Goal</Button>
    </form>
  );
};

export default CourseInput;
  • 인라인 스타일은 객체의 key-value로 추가할 수 있다.
    • key는 카멜 표기법으로 입력한다.
  • 삼항 연산자를 활용하여 조건에 따라 state의 값이 변하고 state 값에 따라 스타일을 다르게 설정할 수 있다.
  • 그러나 이 방법은 인라인으로 사용되기 때문에, CSS에 최우선 순위가 되어 모든 스타일에 오버라이드 된다.


2) 동적 CSS 클래스

특정 클래스에 CSS 스타일을 지정하고 클래스를 state에 따라 변경시켜 스타일을 동적으로 바꿀 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import React, { useState } from 'react';

import Button from '../../UI/Button/Button';
import './CourseInput.css';

const CourseInput = props => {
  const [enteredValue, setEnteredValue] = useState('');
  const [isValid, setIsValid] = useState(true);

  const goalInputChangeHandler = event => {
    if (event.target.value.trim().length > 0) {
      setIsValid(true);
    }
    setEnteredValue(event.target.value);
  };

  const formSubmitHandler = event => {
    event.preventDefault();
    if (enteredValue.trim().length === 0) {
      setIsValid(false);
      return;
    }
    props.onAddGoal(enteredValue);
  };

  return (
    <form onSubmit={formSubmitHandler}>
      
      {/* state를 활용한 동적 클래스*/}
      <div className={`form-control ${!isValid ? 'invalid' : ''}`}>
        <label>Course Goal</label>
        <input type="text" onChange={goalInputChangeHandler} />
      </div>
      <Button type="submit">Add Goal</Button>
    </form>
  );
};

export default CourseInput;
  • 이렇게 css파일로 작업할 때 클래스만으로도 작업할 수 있다.


2. Styled Components

공식문서

컴포넌트 파일에 css파일들을 임포트하여 사용하면, 해당 스타일의 범위를 import한 컴포넌트에만 국한시키지는 않는다.

css 파일은 전역적으로 영향을 미친다. 프로젝트가 커지면 많은 사람들이 같은 코드에서 작업을 하게 되고 이는 css 선택자가 중복될 수도 있다는 의미이다.

Styled Components는 이와 같은 문제를 해결할 수 있다.


1) 기본 개념

Styled Components는 스타일이 첨부되는 컴포넌트에만 영향을 미치고 다른 컴포넌트에는 전혀 영향을 미치지 않는다.

1
$ npm install --save styled-componts


Styled Component는 설정한 스타일을 보고 생성된 클래스 이름을 생성하고 컴포넌트에 적용한다.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import styled from 'styled-components';

// button은 Styled 객체의 메서드이다. 
// ()를 사용하여 호출 하는 대신 ``를 사용하여 호출한다. 
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);
  }
`;

export default Button;
  • button 메서드는 새로운 button 컴포넌트를 반환한다.
    • 백틱 사이에 있는 요소들이 매개변수로 전달되어 해당 스타일이 있는 button 컴포넌트를 반환
  • 가상 선택자의 경우 &:기호를 통해 사용할 수 있다.


2) Props와의 연결

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import React, { useState } from 'react';
import styled from 'styled-components';

import Button from '../../UI/Button/Button';
import './CourseInput.css';

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;
  }
`;

const CourseInput = props => {
  const [enteredValue, setEnteredValue] = useState('');
  const [isValid, setIsValid] = useState(true);

  const goalInputChangeHandler = event => {
    if (event.target.value.trim().length > 0) {
      setIsValid(true);
    }
    setEnteredValue(event.target.value);
  };

  const formSubmitHandler = event => {
    event.preventDefault();
    if (enteredValue.trim().length === 0) {
      setIsValid(false);
      return;
    }
    props.onAddGoal(enteredValue);
  };

  return (
    <form onSubmit={formSubmitHandler}>
      <FormControl invalid={!isValid}>
        <label>Course Goal</label>
        <input type="text" onChange={goalInputChangeHandler} />
      </FormControl>
      <Button type="submit">Add Goal</Button>
    </form>
  );
};

export default CourseInput;
  • &: 해당 태그안에 있는 것에 대해 얘기하고 있어 라고 선언하는 것이다. (중첩 선택자)
  • styled Component 함수에 의해 반환되는 컴포넌는 props를 전달받아 백틱 내부에서 사용할 수 있다.
  • 이렇게 styled 컴포넌트에 전달되는 일부 props에 따라 스타일을 동적인 방식으로 바꿀 수 있다.


3) 미디어 쿼리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import styled from 'styled-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);
  }
`;

export default Button;
  • Styled Component에 미디어 쿼리를 설정할 수도 있다.


3. CSS Moudule

전역 스타일을 쓰지 않고 CSS 파일과 JS를 분리해서 사용하고 싶다면 CSS Module을 사용하면 된다.

css모듈은 그 기능을 지원하도록 설정된 프로젝트에서만 사용가능한데 브라우저에서 코드가 실행되기 전에 코드의 변환이 필요하기 때문이다.

css클래스나 css파일을 가지고 그 클래스 이름을 고유하게 바꾸어 css파일에서 설정한 css스타일의 범위가 이 파일에 임포트하는 컴포넌트에 한정되게 해준다.


1) 기본 개념

1
2
3
4
5
6
7
8
9
10
11
12
13
import React from 'react';

import styles from './Button.module.css';
const Button = props => {
  return (
    // className에 styles객체의 button 클래스를 넣는다. 
    <button type={props.type} className={styles.button} onClick={props.onClick}>
      {props.children}
    </button>
  );
};

export default Button;
  • css파일 이름 뒤에 .module을 붙여야 한다.
    • 이것은 기본적으로 css모듈이 작동하도록 코드를 변환하라고 컴파일 프로세스에게 보내는 신호이다.
    • styles라는 객체의 형태로 import된다.
  • styles객체에는 클래스 명을 key로 접근할 수 있다.
  • 실제로 돔에는 컴포넌트이름_ 클래스 이름_ 고유한 해시값으로 클래스 이름이 생성된다.
    • ex) class="Button_button_2lgkf"


2) 동적 스타일

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import React, { useState } from 'react';

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

const CourseInput = props => {
  const [enteredValue, setEnteredValue] = useState('');
  const [isValid, setIsValid] = useState(true);

  const goalInputChangeHandler = event => {
    if (event.target.value.trim().length > 0) {
      setIsValid(true);
    }
    setEnteredValue(event.target.value);
  };

  const formSubmitHandler = event => {
    event.preventDefault();
    if (enteredValue.trim().length === 0) {
      setIsValid(false);
      return;
    }
    props.onAddGoal(enteredValue);
  };

  return (
    <form onSubmit={formSubmitHandler}>
      
      {*/ CSS Modules을 활용한 동적 클래스 /*}
      <div
        className={`${styles['form-control']} ${!isValid && styles.invalid}`}
      >
        <label>Course Goal</label>
        <input type="text" onChange={goalInputChangeHandler} />
      </div>
      <Button type="submit">Add Goal</Button>
    </form>
  );
};

export default CourseInput;
  • 만약 클래스 이름에 -가 있다면, styles['form-control']로 접근할 수 있다.


This post is licensed under CC BY 4.0 by the author.