본문 바로가기
Front-end/React\RN

리액트 Styled Components , CSS 모듈

by javapp 자바앱 2022. 12. 20.
728x90

 

Styled Components , CSS 모듈

 

React 에서는 컴포넌트 스타일링 방법이 두가지 있음

- Styled Components

- CSS 모듈

 

1. Styled Components

 

"Add Goal" 버튼 같은 경우 Styled Components를 통해 생성된 컴포넌트

 

 

Button.css

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

.button:focus {
  outline: none;
}

.button:hover,
.button:active {
  background: #ac0e77;
  border-color: #ac0e77;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
}

위와 같은 css 파일을 컴포넌트로 생성 가능

 

 

Button.js

import React from 'react';
import styled from 'styled-components';
//import './Button.css';

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);
  }
`; //태그드 템플릿 리터럴


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

export default Button;

가장 위는 root로 전체를 스타일링

 

- 태그는 '&' 기호로 바꿈

button:focus ---> &:focus

 

 

다른 모듈에 <Button ... > 컴포넌트 사용 가능

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

 

 

FormControl,js

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 => {
    setEnteredValue(event.target.value);
  };

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

  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;

const FormControl = styled.div`` : 벡틱으로 css 코드를 감싸고 '태그드 탬플릿 리터럴' 이라고 함.

 

동적으로 속성 설정 가능

    border: 1px solid ${props=>(props.invalid?'red' : '#ccc')};
    background : ${props=>(props.invalid ? '#ffd7d7' : 'transparent')}

 

 

 

 

 


 

2. CSS 모듈

 

import React from 'react';

// 임포트하는 모든 css 파일을 고유하게 만듬
// 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;

styles 를 붙여 css 파일의 클래스를 고유하게 만듬

 

 

CourseInput.js

import React, { useState } from 'react';
import styled from 'styled-components';
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 => {
    setEnteredValue(event.target.value);
  };

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

  return (
    <form onSubmit={formSubmitHandler}>
      <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;

      <div className={`${styles['form-control']} ${!isValid && styles.invalid}`}>

벡틱으로 문자열을 만듬 , !isValid 유효하지 않을 때 && styles.invalid 스타일 적용

 

 

CourseInput.module.css

.form-control {
  margin: 0.5rem 0;
}

.form-control label {
  font-weight: bold;
  display: block;
  margin-bottom: 0.5rem;
}

.form-control input {
  display: block;
  width: 100%;
  border: 1px solid #ccc;
  font: inherit;
  line-height: 1.5rem;
  padding: 0 0.25rem;
}

.form-control input:focus {
  outline: none;
  background: #fad0ec;
  border-color: #8b005d;
}

.form-control.invalid input{
  border-color: red;
  background: #ffd7d7;
}

.form-control.invalid label{
  color:red;
}

 

 

 

 

 

 

 

 

 

댓글