본문 바로가기
JavaScript/React

React) 컴포넌트 스타일링③ - CSS Module (classnames)

by 박채니 2022. 11. 19.
안녕하세요, 코린이의 코딩 학습기 채니 입니다.
[리액트를 다루는 기술]의 책을 참고하여 포스팅한 개인 공부 내용입니다.

 

컴포넌트 스타일링

 

CSS Module

- CSS를 불러와서 사용할 때 클래스 이름을 고유한 값자동으로 [파일 이름]_[클래스 이름]_[해시값] 형태로  만들어줌

- 컴포넌트 스타일 클래스 이름 중첩되는 현상 방지

- v1의 create-react-app에선 웹 팩에서 css-loader 설정을 별도 해줘야 하지만, v2 버전 이상부턴 설정할 필요 없이 .module.css 확장자로 파일 저장만 한다면 CSS Module 적용

 

CSSModule.module.css

/* 자동으로 고유해질 것이므로 흔히 사용되는 단어를 클래스 이름으로 마음대로 사용 가능 */

.wrapper {
    background: black;
    padding: 1rem;
    color: white;
    font-size: 2rem;
}

/* 글로벌 CSS를 작성하고 싶다면 */
:global .something {
    font-weight: 800;
    color: aqua;
}

CSS Module 사용 시, 클래스 이름을 지을 때 고유성에 대해 고민하지 않아도 됩니다.

해당 클래스는 스타일을 직접 불러온 컴포넌트 내부에서만 작동하기 때문!

만일, 특정한 클래스가 웹 페이지 전역적으로 사용되는 경우 :global앞에 입력하여 글로벌 CSS를 명시해줍니다.

 

CSSModule.js

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

const CSSModule = () => {
    console.log(styles);
    return(
        <div className={styles.wrapper}>
            안녕하세요, 저는 <span className="something">CSS module!</span>
        </div>
    )
}

export default CSSModule;

CSS Module이 적용된 스타일 파일을 불러오면 객체를 전달 받게 됩니다.

이는 CSS Module에서 사용한 클래스 이름과 해당 이름을 고유화한 값key-value 형태로 들어있습니다.

console.log(styles) 출력 값

[파일 이름]_[클래스 이름]_[해시값] 형태로 출력되는 것을 확인할 수 있습니다.

해당 클래스 이름을 사용하려면 {styles.[클래스이름]} 형태로 사용 / :global의 경우 문자열로 넣어주어 사용합니다.

 

App.js

import CSSModule from './CSSModule';

class App extends Component {
  render() {
    return (
      <div>
        <CSSModule />
      </div>
    );
  }
}

export default App;

 

만일 CSS Module을 사용한 클래스 이름을 두 개 이상 적용하고 싶다면?

 

CSSModule.module.css

/* 자동으로 고유해질 것이므로 흔히 사용되는 단어를 클래스 이름으로 마음대로 사용 가능 */

.wrapper {
    background: black;
    padding: 1rem;
    color: white;
    font-size: 2rem;
}

/* 추가 */
.inverted {
    color: black;
    background: white;
    border: 1px solid black;
}

/* 글로벌 CSS를 작성하고 싶다면 */
:global .something {
    font-weight: 800;
    color: aqua;
}

 

CSSModule.js

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

const CSSModule = () => {
    console.log(styles);
    return(
        <div className={`${styles.wrapper} ${styles.inverted}`}>
            안녕하세요, 저는 <span className="something">CSS module!</span>
        </div>
    )
}

export default CSSModule;

백틱을 이용하여 문자열을 합하여 적용해주었습니다.

 

classnames

 

CSS 클래스를 조건부로 설정할 때 매우 유용한 라이브러리!

사용을 위해 설치해주겠습니다.

$ yarn add classnames

 

기본 사용법

import classNames from 'classnames';

classNames('one', 'two'); // 'one two'
classNames('one', { two: true }); // 'one two'
classNames('one', { two: false }); // 'one'
classNames('one', ['two', 'three']); // 'one two three'

const myClass = 'hello';
classNames('one', myClass, { myCondition: true }); // 'one hello myCondition'

위와 같이 여러 파라미터를 조합해 CSS 클래스를 설정할 수 있습니다.

이를 이용해 props 값에 따라 다른 스타일을 주게 될 수도 있겠죠.

 

예시

const MyComponent = ({ highlighted, theme }) => (
	<div className={classNames('MyComponent', { highlighted }, theme)}>Hello</div>
);

highlighted 값이 true이면 highlighted 클래스가 적용, false적용되지 않게 되고

theme은 그대로 클래스 적용이 될 것입니다.

 

이 외에도 classnames에 내장되어 있는 bind 함수를 사용하여 더욱 더 간편하게 CSS Module을 사용할 수 있습니다.

bind 함수를 사용하지 않으면 매번 클래스 적용 시 styles.[클래스이름] 형태를 사용해야 하지만,

bind 함수를 이용하여 사전에 미리 styles를 받아 온 후 사용하게끔 설정해 두고 cx('클래스 이름', '클래스 이름2') 형태로 사용할 수 있습니다.

 

CSSModule.js - classname bind 함수 적용

import classNames from 'classnames/bind'
import styles from './CSSModule.module.css';

const cx = classNames.bind(styles);

const CSSModule = () => {
    return(
        <div className={cx('wrapper', 'inverted')}>
            안녕하세요, 저는 <span className="something">CSS module!</span>
        </div>
    )
}

export default CSSModule;

훨씬 편리하게 사용할 수 있는 것을 확인할 수 있습니다.

 

Sass와 함께 사용하기

 

파일 이름 뒤에 .module.scss 확장자를 사용해주어 CSS Module과 Sass를 같이 사용할 수 있습니다.

 

CSSModule.module.css → CSSModule.module.scss

.wrapper {
    background: black;
    padding: 1rem;
    color: white;
    font-size: 2rem;
    &.inverted {
        // inverted가 .wrapper와 함께 사용 되었을 때 적용
        color: black;
        background: white;
        border: 1px solid black;
    }
}

/* 글로벌 CSS를 작성하고 싶다면 */
:global {
    // :global {}로 감싸기
    .something {
        font-weight: 800;
        color: aqua;
    }
    // 다른 클래스도 적용하고 싶다면 여기에 만들면 됨!
}

 

CSS Module이 아닌 파일에서 CSS Module 사용하기

 

CSS Module이 아닌 일반 .css/.scss 파일에서도 :local을 사용하여 CSS Module 사용 가능!

:local .wrapper {
	/* 스타일 */
}

:local {
	.wrapper {
    	/* 스타일 */
    }
}