Chapter7. 리액트 컴포넌트 스타일링

Muru·2023년 11월 1일

[React] 지식 저장소

목록 보기
14/30
post-thumbnail

7.1 : Chap7에선 무엇을 배우는가?

우리가 웹페이지를 볼때 어떤 색상같은 스타일의 요소들이 모두 정적이지는 않다.
어느 특정 부분을 클릭하면 경고창을 암시하는 빨간색 스타일이 적용되거나 하는등의 동적인 CSS 스타일을 확인 할 수 있다

이번 단원에서는 조건부 혹은 동적인 방법으로 스타일을 설정하는 방법을 알아본다.

크게 세가지를 학습한다.

  • 스타일을 적용하는 컴포넌트의 범위를 정하는 가장 인기있는 두 접근 방법

    1. 동적 인라인 스타일 설정
    2. 동적 CSS 클래스 설정
  • styled 컴포넌트

    1. 인기 있는 서드 파트 라이브러리이다.
    2. 고유한 범위를 가진 스타일로 미리 스타일이 지정된 컴포넌트 설정 가능하다.
  • CSS 모듈 개념




7.2 : 동적으로 인라인 스타일 설정하기

다음 코드에서 색상변경 버튼을 클릭하면 p 태그의 색깔이 바뀌도록 설정해보자.


   <div>
    <p>안녕하세요</p>
    <button>색상 변경</button>
   </div>


  const [isClick, setIsClick] = useState(true);
  const buttonOnclickHandler = () => {
   setIsClick((isClick) => !isClick);
  };
  
  return (
   <div>
    <p style={{ color: isClick ? "black" : "red" }}>안녕하세요</p>
    <button onClick={buttonOnclickHandler}>색상 변경</button>
   </div>
  );

클릭전

클릭후

다시클릭






7.3 : 동적으로 CSS 클래스 설정하기

이번에는 인라인이 아닌 CSS 클래스로 동적 설정하는 방법을 알아보자.
app.js

const [isClick, setIsClick] = useState(true);
  const buttonOnclickHandler = () => {
   setIsClick((isClick) => !isClick);
  };
  return (
   <div>
    <p className={`${!isClick  ? 'style-blue' :  'style-black' }`} >안녕하세요</p>
    <button onClick={buttonOnclickHandler}>색상 변경</button>
   </div>
  );
}

style.css

.style-black {
   color : black;
}

.style-blue {
   color : blue;
   font-weight: bold;
   font-size : large;
}
  • 템플릿 리터럴을 사용하여 문자열 사이에 표현식을 삽입하자.
    표현식을 삽입할때는 ${ .. } 이런식으로 달러표시와 중괄호를 써주면된다.

클릭전

클릭후

다시클릭




7.4 : Styled Components 소개

7.4.1 : 왜 Styled Components를 사용해야하는가??

우리는 보통 이런식으로 사용했을 것이다.
UserData.js와 UserData.css 파일이 있다고 했을때
UserData.css 파일의 선택자 이름을 UserData.js 파일에서 사용하는식이다.

UserData.js

import './CourseInput.css';

UserData.css

. Form-control{
 . . .
}

# Form {
 . . .
}

위의 방식처럼 사용은 해도 되지만 협업을 하는 프로젝트에서는 문제의 여지가 있다.
예를들면 Form-control이 응용프로그램에서 다른 위치에 사용을 또 하고 있었다면?
내가 코딩한 컴포넌트에서도 영향을 줄 수 있고 그런 상황은 피하는것이 좋겠다.

그래서 사용하는게 Styled Components

7.4.2 : Styled Components 패키지를 설치하자.

npm install styled-components

버전이 맞지 않아서 npm ERR! 같은 현상이 나올 수 있다. 다음과 같이 입력해주자

npm install styled-components@latest

7.4.3 사용방법

App.js

import Button from "./components/Button";

function App() {
  return (
   <div>
    <Button>파란색 버튼</Button>
   </div>
  );
}

Button.js

import styled from 'styled-components';

const Button = styled.button`  
background: #5B78AC;

&:hover {
background : red;
}
`; 
export default Button;
  • styled객체 뒤의 메소드는 HTML 요소의 거의 모든 태그들을 담고있다.
    ex) p,h1,h2 등.. 지금 사용한 메소드는 button 메소드를 사용했다.
  • 이 메소드는 특별하다. 소괄호() 로 호출하는 메소드가 아니라 `` 백틱을 사용하여 호출한다.
  • 선택자는 모두 없애준다. 백틱사이에 있는 사용할 스타일을 button에 직접적으로 영향을 줄것이기 때문
  • 가상선택자는 “&” 기호를 붙여 사용해야한다.
    위 코드를 가지고 해석하면 “이버튼에 hover가 발생하면 해당 백그라운드 스타일을 적용해줘 ! ”

Button.js 파일에서 위 코드와 같이 button 메소드를 사용해주면 새로운 button 컴포넌트를 반환한다.

스타일이 잘 입혀진것을 볼 수 있다.

가상선택자(hover)도 적용이 잘 되는것을 볼 수 있다.

7.4.4 styled-components는 다른 컴포넌트에 영향을 주지 않는다.

styled-components를 적용한 동일내용의 CSS가 담겨있는 각기다른 button의
BookButton.js 와 BookButton2.js 컴포넌트 파일이 있다고 해보자.

BookButton.js

import styled from 'styled-components';
const BookButton = styled.button`  
background: red;
&:hover {
background : blue;
}
`; 
export default BookButton;

BookButton2.js

import styled from 'styled-components';
const BookButton2 = styled.button`  
background: red;
&:hover {
background : blue;
}
`; 
export default BookButton2;

Book.js

import BookButton from "./BookButton";
import BookButton2 from "./BookButton2";
const Book = () => {
   return ( <div>
     <BookButton>BookButton.js</BookButton>
     <BookButton2>BookButton2.js</BookButton2>
   </div> );
};
export default Book;

Book.js 에서 동일 CSS 내용을 담고있는 서로 다른 styled-components 파일을 적용했을때 ClassName은 동일할까??

당연하게도 다르다. 같다고 한다면 styled-componets를 사용할 목적을 잃게된다.

이상하게 생긴 저 클래스 이름은 styled-components 패키지에 의해 동적으로 생성된 클래스 이름이다.

그래서 아래의 코드처럼 styled-componets을 적용한 이 클래스들을 전역 CSS로 추가해도 되는 이유다. 여기서 설정한 스타일은 앱에있는 다른 컴포넌트에 절대 영향을 주지 않는것이다.

const BookButton2 = styled.button`  
background: red;
&:hover {
background : blue;
}
`



7.5 : Styled Components & 동적 Props

평소에 우리는 특정데이터나 상태를 컴포넌트에게 props를 전달하는것이 가능했다.
그렇다면 components를 이용한 컴포넌트에도 props를 전달하는것이 가능할까?
미리 결론을 짓자면 가능하다. 이를 활용하여 동적으로 css를 설정하는것도 가능하다.

다음과같은 버튼을 누른다면 색상반전하고자 하는 코드를 짜려고 한다.
빨간색 글씨는 파란색 글씨로 , 파란색 배경은 빨간색 배경으로.

Book.js

import React, { useState } from "react";
import BookButton from "./BookButton";
const Book = () => {
  const [isClick, setIsClick] = useState(true);

  const BookClickHandler = () => {
   setIsClick((isClick) => !isClick);
  };
  return (
   <div>
    <BookButton onClick={BookClickHandler} isClick={isClick}>버튼</BookButton>
   </div>
  );
};
export default Book;

BookButton.js

import styled from 'styled-components';
const BookButton = styled.button`  
padding: 5rem 5rem;
border: 10px solid gray;
color: ${props => (props.isClick ? 'red' : 'blue')};
background : ${props => (props.isClick ? 'blue' : 'red')};
box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
cursor: pointer;
`; 
export default BookButton;

사용하는 방법은 기존에 컴포넌트에게 속성을 건네주어 사용했던방식과 유사하다.
다만 속성(props)을 받은것은 달러표시($) 와 중괄호 표기법을 사용해야함을 알아두자.

마우스로 클릭하여 색상반전이 잘 일어난 결과를 볼 수있다.






7.6 : Styled Components & 미디어 쿼리

7.6.1 : 미디어쿼리란?

웹 개발에서 사용되는 CSS 기술로 반응형 웹 디자인의 핵심 요소로 사용되고 있다.
다양한 장치(웹, 태블릿PC, 핸드폰)에 ᄄᆞ라 유연하게 화면이 출력될 수 있게끔 한다.

사용방법 : @media (조건문) { 실행코드 }

//가로 해상도가 576px 보다 큰화면에서 적용한다.
@media ( min-wdith: 576px ) { . . . }

//가로 해상도가 768px 보다 큰화면에서 적용한다.
@media ( min-wdith: 768px ) { . . . }

7.6.2 : 사용방법

Syled Components 역시 미디어 쿼리를 사용하는것이 가능하다.

이 웹페이지가 더 큰 디바이스에서 실행된다고 가정할때 해당 디바이스에 맞춰서 너비가 늘어나는 코드를 작성해보자.
Book.js

import React, { useState } from "react";
import BookButton from "./BookButton";
import styled from 'styled-components';
Book.js
const Book = () => {
  const [isClick, setIsClick] = useState(true);
  const BookClickHandler = () => {
   setIsClick((isClick) => !isClick);
  };
  const Forms = styled.div`
  background : black;
  `;
  return (
   <Forms>
    <BookButton onClick={BookClickHandler} isClick={isClick}>버튼</BookButton>
   </Forms>
  );
};
export default Book;

BookButton.js

import styled from 'styled-components';
const BookButton = styled.button`  
@media (min-width: 1024px) {
   width : 40rem
}
`; 
export default BookButton;

버튼의 크기가 늘어난것을 확인할 수 있다.





7.7 : CSS 모듈 사용하기

Styled 컴포넌트를 사용하는건 CSS 파일로 저장되지 않는다.
Button.js 같이 컴포넌트로 사용하는것 말고 CSS 파일로 사용하며 다른 컴포넌트에 영향을 주지 않도록 하는 방법은 없을까?

CSS 모듈을 사용하여 깔끔하게 CSS파일과 자바스크립트를 분리해보자.

App.js

import React, { useState } from "react";
import styles from './BookButton.module.css';

const Book = () => {
  return (
   <div>
    <button className = {`${styles.button}`}>버튼</button>  
    </div>
  );
};
export default Book;

BookButton.module.css

.button {
  width: 10rem;
  padding: 5rem 5rem;
  border: 10px solid gray;
  color: red;
  background: blue;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
  cursor: pointer;
}
  • CSS 모듈의 파일명은 중간에 module을 추가해주어야 한다.
  • 모듈을 가져올때 규칙은 import “아무이름“ from 경로로 사용하고 보통 아무이름에 styles가 통상적으로 사용된다.
  • Styled 컴포넌트와 다르게 .button같은 요소를 생략할 수 없다.


css 모듈 역시 동적으로 사용하는것이 가능하다.
App.js

import React, { useState } from "react";
import styles from './BookButton.module.css';

const Book = () => {
  const [isClick, setIsClick] = useState(true);
  const BookClickHandler = () => {
   setIsClick((isClick) => !isClick);
  };
  return (
   <div>
    <button
     onClick={BookClickHandler}
     className={`${styles.button} ${isClick &&styles.isClick}`}
    >
     버튼
    </button>
   </div>
  );
};
export default Book;

BookButton.module.css

.button {
  width: 10rem;
  padding: 5rem 5rem;
  border: 10px solid gray;
  color: red;
  background: blue;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
  cursor: pointer;
}

.button.isClick {
  width: 10rem;
  padding: 5rem 5rem;
  border: 10px solid gray;
  color: blue;
  background: red;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
  cursor: pointer;
}

.div {
  background: white;
  &input {
   display: block;
   width: 10rem;
   font: inherit;
   line-height: 1.5rem;
   padding: 0 0.25rem;
  }
}
className={`${styles.button} ${isClick &&styles.isClick}`}

이 구문을 잘 알아두자. 처음부분의 ${styles.button} 부분은 변환된 클래스 이름이고, 두번째 ${isClick &&styles.isClick} 이 부분은 추가 적용되는 부분이다.

  • 뒷부분으로 바뀌는것이 아니라. 뒷부분이 “추가”되는것이다.
    동일 css 스타일이 있다면 해당 동일 CSS 스타일이 나중에 써진것이 덮어씌워지는것임을 유의해야한다.
    처음부분에서 뒷부분으로 적용되었다고 착각할 수 있기 때문이다.
    ( 좀더 좋게 코드를 짜는방법이 있을거 같긴하다..

버튼 누르기전 ( styles.button 스타일만 적용된 상태 )

버튼 누른후 ( styles.button 과 styles.isClick 두개의 스타일이 적용된 상태 )




CSS 모듈에 미디어 쿼리를 짜는것 역시 가능하다. 사용하고자하는 요소에 써주면된다.
BookButton.module.css

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

0개의 댓글