공부/React

[React 시작하기] 03. React Component Styling

도리암 2022. 5. 17. 22:36

Style Loaders

각 loader는 작성한 파일들의 문법을 해석하고 적용시키는 역할이다.

webpack은 babel-loader, style-loader, css-loader 등의 여러가지 loader를 사용한다.

각 Loader 살펴보기

CRA로 만들어진 프로젝트를 eject하게 되면 webpack 기반의 프로젝트로 재구성되어 각 loader 들이 수면위로 나온다.

npx create-react-app style-loaders-example

cd style-loaders-example

npm run eject

/config/webpack.config.js

위와 같이 각 확장자에 대해 연결되는 Loader들이 설정돼있다.

CSS, SASS

css파일을 적용시키려면 js에서 다음의 문구를 추가하면 된다.

import './App.css';

React에서는 여러 CSS파일을 한번에 import할 때, 특정 컴포넌트에 대한 특정 스타일을 따로 지정하는게 불가능하다.

다시 말하면, 1.css 파일과 2.css 파일에 모두 .header 속성이 있는 경우, header 클래스를 가지는 요소에 1 또는 2를 취사선택하여 적용할 수가 없다는 의미다.

 

따라서 CSS 방법론(className 차별화)이 개발되었으며, CSS 방법론에는 크게 SMACSS, BEM, OOCSS가 있다.

CSS 방법론 (tistory.com)

 

CSS 방법론

대규모의 페이지 및 다수의 인원이 작업을 해야할 경우 클래스 명을 일관성 있게 유지해야할 필요가 있다. 그렇기 때문에 생겨난 것이 CSS 방법론이다. CSS 방법론은 다음의 형태를 추구한다. 코

riam.tistory.com

이렇게 작성한 것을

이런식으로 작성할 수도 있다.

SCSS는 위와 같이 작성할 수 있다.

 

CSS module, SASS module

위와 같이 CSS 방법론을 이용할 수도 있지만 모듈을 사용하면 Scope 오염을 방지할 수 있다.

Adding a CSS Modules Stylesheet | Create React App (create-react-app.dev)

 

Adding a CSS Modules Stylesheet | Create React App

Note: this feature is available with react-scripts@2.0.0 and higher.

create-react-app.dev

[Filename]_[Classname]__[Hash]

위처럼 className을 [Filename]_[Classname]__[임의의 hash 값] 으로 바꿔준다.

위의 hash값을 실제 컴포넌트에 적용하기 위해서는 다음과 같이 바인딩이 필요하다.

<div className={styles["App"]}>

사용 예시

Classnames 모듈

CSS module을 사용하여 클래스 이름을 사용할 때, 조건부로 css를 적용하게 될 경우 클래스 명이 너무 길어지게 된다.

classnames - npm (npmjs.com)

 

classnames

A simple utility for conditionally joining classNames together. Latest version: 2.3.1, last published: a year ago. Start using classnames in your project by running `npm i classnames`. There are 34271 other projects in the npm registry using classnames.

www.npmjs.com

classnames 모듈을 사용하게 되면 다음과 같이 True인 값만 클래스로 넣을 수 있다.

import classNames from 'classnames';

console.log(classNames('foo', 'bar')); // "foo bar"
console.log(classNames('foo', 'bar', 'baz')); // "foo bar baz"

console.log(classNames({ foo: true }, { bar: true })); // "foo bar"
console.log(classNames({ foo: true }, { bar: false })); // "foo"
console.log(classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, '')); // "bar 1"
console.log(classNames(styles.button, styles.loading)); // Button_button__2Ce79 Button_loading__XEngF

그런데 위의 방법은 기존에 사용하던 방식과 큰 차이가 없다.

classnames/bind

다음과 같이 cx 에 classNames.bind(styles)를 하게 되면 간소화가 가능하다.

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

const cx = classNames.bind(styles);

console.log(cx('button', 'loading')); // Button_button__2Ce79 Button_loading__XEngF
console.log(cx('button', { loading: false })); // Button_button__2Ce79

state의 loading이 true가 되면 loading 이라는 클래스이름이 추가된다. ({ loading: loading }) 축약된 형태

Styled Components

컴포넌트 자체에 스타일을 적용시키는 방법이다.

태그 컴포넌트는 .jsx 파일로 작성한다.

npm i styled-components

 

/src/components/StyledButton.jsx

styled.기본제공컴포넌트명``

styled(사용자 제작 컴포넌트명)``

위의 벡틱기호 사이에 적용할 스타일을 작성하면 된다.

기본적으로 제공되는 컴포넌트는 .기호로, 사용자가 직접 만든 컴포넌트는 ()를 통해 접근하면 된다.

작성한 스타일은 DOM의 Header에 추가된다.

주의할 점은, 문자열로 작성하게 되므로 오류 수정이 어렵다는 단점이 있다.

props

props를 통해 추가적인 스타일 지정이 가능하다.

엄연히 문자열 내부에 CSS문법을 사용하는 것이므로 벡틱 기호로 감싸주는 것을 잊지 말아야 한다.

상속

사용자가 임의로 만든 컴포넌트를 상속받아서 추가적으로 사용할 수 있다.

다른 태그처럼 사용하기 (as 키워드)

사용자 지정 컴포넌트를 특수한 기능을 가진 태그처럼 사용하고 싶을 때 쓰는 방법이다.

예를 들어 a태그처럼 사용하고 싶다면 다음과 같이 사용한다.

또한 태그 뿐만이 아닌 다른 컴포넌트도 사용할 수 있다.

props를 통해 조건부로 서식 변경하기

만약 props를 통해 일부 속성이 들어오게 되면, || 기호를 통해 props 값과 디폴트 값을 구분해주면 된다.

속성: ${props => props.속성 || '디폴트값'} ;

컴포넌트 자체를 특수 컴포넌트화 하기

styled.태그명.attr(props => ({속성들})) 을 하게 되면 해당 컴포넌트를 특수 태그로 사용할 수 있다.

사용자 지정 컴포넌트를 a 태그로 사용할 수 있게 만든 모습이다.

target: '_BLANK'를 하면 항상 새창에서 열릴 수 있도록 할 수 있다.

 

React Shadow

이것 또한 Scope 오염 방지를 위한 모듈이다.

npm i react-shadow

오른쪽 styles = ``; 에 ... 대신 왼쪽의 스타일이 존재한다고 생각하면 된다.

 

<root.div>로 감싼 영역은 외부의 styles로부터 영향을 받지 않는 독립적인 구역이 된다.

따라서 외부의 스타일이 내부로 들어오지 못하고, 내부의 스타일도 외부로 영향을 미치지 못하게 된다.