記錄

[React 스터디 - 6] 리액트 CSS 적용 방법 본문

FRONTEND STUDY/React

[React 스터디 - 6] 리액트 CSS 적용 방법

prts 2022. 12. 25. 23:18

01 Inline style

html 태그 안에 직접 입력하는 방법으로, style={ } 형식으로 입력한다. 안에는 json 형식으로 { 속성명: '속성값' } 으로 입력한다. 일반적인 css 문자열을 작성할 때 사용하는 케밥 케이스(kebab case)가 아닌 camelCase를 사용하는데, JSX에서는 인라인 스타일을 자바스크립트 객체로 받아들이기 때문이다.

//html, kebab case
<h1 style="background-color: purple">텍스트</h1>

//jsx, camelCase
<h1 style={{ backgroundColor: "purple" }}>텍스트</h1>

다음과 같이 Javascript 객체를 이용해 작성할 수도 있다.

const divStyle = {
  color: 'blue',
  backgroundImage: 'url(' + imgUrl + ')'
}

function HelloWorldComponent(){
   return <div style={divStyle}>Hello World!</div>
}

숫자 인라인 스타일 프로퍼티일 경우, px를 자동으로 추가하기 때문에 다른 단위를 원하면 그 단위를 따로 입력해야 한다.

//px를 단위로 자동 추가
<div style={{ height: 10 }}>10px</div>

//다른 단위를 명시적으로 입력
<div style={{ height: '10%' }}>10%</div>

+ 인라인 스타일 적용은 가장 높은 우선순위를 가지나, 복잡한 컴포넌트에서 스타일 작성이 어려워지기 때문에 권장하지 않는다.

+ 인라인 스타일도 삼항연산자를 이용한 조건부 렌더링이 가능하다.

02 CSS, SASS

CSS 또는 SASS를 이용해 파일을 분리해서 class를 설정해 그 class에 적용할 각종 스타일을 작성하고, 리액트 컴포넌트 파일에 css를 import하는 방식이다.

@import './button.css';

//scss
@import './button.scss';

SASS 사용 시에는 프로젝트 디렉터리에 node-sass 라는 패키지를 설치해야 한다. SASS는 전처리기이기 때문에 그 자체로는 웹에서 동작하지 않으며, node-sass 패키지를 사용하여 Sass를 CSS로 컴파일 후 컴파일된 CSS가 웹에서 동작한다. SASS를 사용할 시 CSS에서 변수, 연산자, 함수, extend, import 등을 사용할 수 있기 때문에 코드의 재사용성 및 가독성이 높아지고, 유지보수가 용이해진다.

//npm
npm install -g node-sass

//yarn
$ yarn add node-sass

className을 통해 조건부 렌더링이 가능하다.

*조건부 렌더링: 특정 조건에 따라 다른 결과물을 렌더링 하는 것으로, props나 state에 css 클래스를 의존해 JavaScript의 조건 처리처럼 동작하는 것

//active 상태면 menu-active 라는 클래스를 추가
render() {
  let className = 'menu';
  if (this.props.isActive) {
    className += ' menu-active';
  }
  return <span className={className}>Menu</span>
}

03 CSS Modules

공식 문서1: https://create-react-app.dev/docs/adding-a-css-modules-stylesheet/
공식 문서2: https://github.com/css-modules/css-modules

css는 기본적으로 전역(global namespace)이기 때문에 일반적은 css 파일로 작성할 시 class 중복이 생기지 않도록 신경써줘야 한다(=해당 모듈만이 아닌 전체 모듈에 css가 적용되기 때문). CSS-module은 css를 모듈처럼 만들어줘서 css 클래스명이 충돌하는 것을 방지할 수 있고, 컴포넌트 단위로 css를 적용할 수 있다. camelCase 사용을 권장하나 강제는 아니다.

 

css 모듈은 js 모듈에 import할 때 하나의 객체로 받아들일 수 있도록 맵핑하고, 클래스 명에 hash값이 붙어 고유한 값으로 변경되어(naming convention) 각 모듈 별로 css가 적용되도록 한다.

import styles from './Button.module.css' //모듈
import './another-stylesheet.css'  //일반 css

class Button extends Component {
  render (){
    return <button className={styles.error}>Error Button</button>;
  }
}

//style.error 이런 식으로 접근하기 때문에 일반 css에 있는 error 클래스와 충돌이 발생하지 않음

Composition

다른 클래스에 해당하는 코드에서 compose하면 그 코드를 그대로 사용 가능하다. 같은 css 또는 다른 css에서도 가져올 수 있다.

.className {
  color: green;
  background: red;
}

.otherClassName {
  composes: className;
  color: yellow;
}

React 에 CSS Module 추가

create-react-app 으로 환경설정했으면 별다른 설정 없이 바로 사용 가능하지만(webpack 에서 사용하는 css-loader 에서 지원), 아닐 경우 추가적인 세팅을 해야 한다.

CRA를 사용한다면, 기존 [name].css를 [name].module.css로 확장자명을 변경해주면 된다. (scss도 동일하다)

import Style from './Component1.module.css';

export const Component1 = () => {
  return (
    <div className={Style['component-class01']}>
      <p>Component1</p>
    </div>
  );
};

전역적인 클래스명이 필요할 경우, CSS Module에서 :global을 이용하면 된다.

:global .page-wrap {
  // ...
}

classNames

동적인 클래스 작성을 위해서는 classNames라는 패키지를 사용한다. classNames의 bind 기능을 이용하면 좀 더 편리하게 조건부 스타일링을 할 수 있다. CSS 클래시 이름을 지정해 줄 때 cx('클래스이름') 과 같은 형식으로 편하게 사용 할 수 있어 여러 개의 클래스를 사용하거나 조건부 스타일링을 할 때 사용한다.

$ npm install classnames
$ yarn add classnames
import Style from './Component1.module.css';
import classNames from 'classnames/bind';

const cx = classNames.bind(Style);

export const Component1 = () => {
  return (
    <div className={cx('component-class01', { type01: true })}>
      <p>component1</p>
    </div>
  );
};

//기본적으로 component-class01이라는 클래스 명이 있으면서 true/false 조건에 따라 type01이라는 클래스가 부여되게 된다

04 CSS-in-JS : Styled-component

공식문서1: https://styled-components.com/
공식 문서2: https://ko.reactjs.org/docs/faq-styling.html

말 그대로 외부에 css 파일을 따로 분리해 작성하는 것이 아니라 JavaScript 파일에 css를 작성하는 방법이다. 기본적으로 지원되는 기능이 아니라 라이브러리를 설치해야 한다. 가장 대중적인 CSS-in-JS 라이브러리는 styled-component다.

//npm
$ npm install --save styled-components
//yarn
$ yarn add styled-components

위에서 설치한 styled-components 패키지에서 styled 함수를 import해서 리액트 컴포넌트에 원하는 스타일을 적용한다.

import React from 'react';
import styled from 'styled-components';

//h1 태그에 스타일을 작성
const Title = styled.h1`
  font-size: 1.5rem;
  text-align: center;
  color: palevioletred;
`;

//wrapper 스타일 작성
const Wrapper = styled.section`
  padding:4em;
  background: papayawhip;
`
//출력
function Main(props) {
  return(
    <Wrapper>
       <Title>
           Hello World!
       </Title>
    </Wrapper>
  )
}

export default Main;

styled-component는 ES6의 Tagged Template Literals을 사용해서 스타일을 정의한다. styled 함수는 해당 스타일이 적용된 컴포넌트를 반환한다.

 

Tagged Template Literals

이 개념을 이해하기 위해서는 Template Literal 에 대한 이해가 필요하다. Template Literal은 ES6 에서 새롭게 도입된 기능으로, 백틱(`)  을 사용하여 문자열과 변수를 함께 사용할 수 있어 동적인 문자열 처리에 유용한 기능이다.

//untagged-단순 문자열
`string text`

//대체 가능한 expression 포함된 문자열
`string text ${expression} string text`

//tagged template literal
//파라미터로 expression 으로 구분된 문자열 배열과 expression 이 순서대로 들어간 형태로 호출
func `string text ${expression} string text`;

Tagged Template literal은 템플릿 리터럴의 발전된 형태로써, 함수 형태로 사용할 수 있다. Tagged Template Literals 문법을 사용하면 타입에 상관없이 Function, Number, Array, Object 등을 전달하고 실행할 수 있다. 또한 props를 사용해서 동적으로 변화하는 값을 넣어 가변 스타일링을 적용할 수 있다.

import React from 'react';
import styled from 'styled-components';

const Button =styled.button`
   color: ${ props => props.dark ? "white": "dark" };
   background: ${ props => props.dark ? "black" : "white" };
   border: 1px solid black;
`

function ChangeButton(props){
   return (
      <div>
           <Button>Light</Button>
           <Button dark>Dark</Button>
      </div>
   )
}

export default ChangeButton;

넘겨야 할 prop 값이 많아질 경우,  ...props 구문(rest parameter)을 사용해서 children 외 모든 prop을 전달할 수도 있다.

import React from "react";
import styled, { css } from "styled-components";

const StyledButton = styled.button`
  padding: 6px 12px;
  border-radius: 8px;
  font-size: 1rem;
  line-height: 1.5;
  border: 1px solid lightgray;

  ${(props) =>
    props.primary &&
    css`
      color: white;
      background: navy;
      border-color: navy;
    `}
`;

function Button({ children, ...props }) {
  return <StyledButton {...props}>{children}</StyledButton>;
}

기존에 작성한 styled-components의 스타일을 확장할 수도 있다.

const Button=styled.button`
   //기존 속성
`;

const RoundedButton = styled(Button)`
  //추가할 속성
`;

참고자료

 

https://react.vlpt.us/styling/02-css-module.html

https://pxd-fed-blog.web.app/css-module/

https://goddaehee.tistory.com/304

https://mygumi.tistory.com/395

https://www.daleseo.com/react-styled-components/

 

 

 

'FRONTEND STUDY > React' 카테고리의 다른 글

JSON-SERVER  (0) 2023.02.20
[React 스터디] SPA, Routing  (0) 2023.01.09
[React 스터디-5] List, Key  (0) 2022.12.18
[React Study - 5] Life cycle, useEffect()  (0) 2022.12.11
[React 스터디 - 4] State  (0) 2022.12.04
Comments