SCSS & CSS Module

seul_velog·2022년 4월 19일
3

React

목록 보기
10/11
post-thumbnail

1. SCSS

Sass(Syntactically Awesome Style Sheets)
: CSS pre-processor(CSS전처리도구, CSS전처리기) 로서, 코드의 재활용성과 가독성을 높여주어 유지보수를 용이하게 해준다.

  • 웹에서는 CSS만 동작한다. 따라서 Sass에서 CSS로 변환해야하는데, 그 과정을 ‘컴파일(compile)'이라고 한다.
  • Sass문법으로 프로젝트를 진행하고 웹에서 동작 가능한 표준의 CSS로 컴파일하여 사용자의 브라우저에서 동작할 수 있도록 만든다.
  • 프로젝트에서 Sass 사용하기 $ yarn add node-sass

✍️ Sass와 SCSS의 차이점은?

  • Sass의 3버전에서 새롭게 등장한 SCSS는 CSS 구문과 완전히 호환되도록 새로운 구문을 도입해 만든 Sass의 모든 기능을 지원하는 CSS의 상위집합(Superset) 이다.
  • 즉, SCSS는 CSS와 거의 같은 문법으로 Sass 기능을 지원한다. 😀



SCSS 살펴보기

SCSS의 주석

/* */
//

  • 위와 같이 두 가지가 제공된다.
    // 은컴파일 과정에서 css로 변환된 결과로 나타나지 않는다. 따라서 변환된 후에도 주석이 남아있어야 한다면 표준 /* */ 주석을 사용한다.

자식요소 선택하기

> 를 이용한다.

// ex.)
.container {
  > ul {
    li {
      .name {
        color: rgb(102, 105, 255);
      }
      .age {
        color: rgb(38, 179, 132);
      }
    }
  }
}

상위(부모) 선택자 참조

& 를 이용한다.

// ex.)
.btn {
  padding: 5px 15px;
  &.active {
    color: red;
  }
}

중첩 속성

  • font- , margin- , padding- 등과 같이 동일한 네임 스페이스를 가지는 속성들에 다음과 같이 사용할 수 있다. (네임스페이스가 동일하다 → 어떤 속성이 가지고 있는 이름부분의 영역이 동일하다)
// ex.)
.box {
  font: {
    weight: bold;
    size: 10px;
    family: sans-serif;
  };
  margin: {
    top: 10px;
    left: 20px;
  };
  padding: {
    bottom: 40px;
    right: 30px;
  };
}

변수설정

$ 를 이용한다.

  • 선언된 범위 내에서 유효범위를 가진다.
  • {} 밖과 {} 안에서 같은 변수를 새롭게 재정의할 수 있고, 블록 범위 아래에서 영향을 미친다. (재할당 가능)
$size: 100px;

산술연산

  • 산술연산시 단위를 맞춰주어야 한다.
  • calc() 함수를 사용하면 다른 단위라도 연산이 가능하다. width: calc(100% - 200px)

재활용하기

  • @mixin@include 키워드와 함께 이름을 붙여서 사용한다.

내장함수

  • 이미 scss 내부에 구현이 되어 있는 색상 내장 함수의 경우 별도의 선업 없이도 바로 사용할 수 있다.
  • mix() : 첫번째 인수와 두번째 인수를 섞어서 새로운 색상을 표현한다.
    $color: royalblue;
    background-color: mix($color, pink); // 연보라색
  • lighten() & darken() : 첫 번째 인수에 특정 색상을 입력, 두 번째 인수에 수치를 입력한다. 해당컬러의 명도를 조절한다.
    background-color: lighten($color, 30%); // 첫 번째 인수의 색상을 30% 밝게 한다.
  • saturate() & desaturate() : 해당 컬러의 채도를 조정한다.
    background-color: desaturate($color, 30%);
  • grayscale() : 해당 컬러의 톤에서 그레이스케일로 변환한다.
    background-color: grayscale($color);
  • invert() : 해당 컬러를 반전시킨다.
    background-color: invert($color);
  • rgba() : 해당 컬러의 투명도를 조절한다.
    background-color: rgba($color, 0.5); // 50% 만큼 불투명 (반투명)





2. classnames 라이브러리

조건부 스타일링을 할 때 함수의 인자에 문자열, 배열, 객체 등을 전달하여 손쉽게 문자열을 조합 할 수 있게 해준다.

  • 조건부로 CSS 클래스를 넣어주고 싶을때는 편하게 classnames 라는 라이브러리를 사용할 수 있다.
classNames('foo', 'bar'); // 'foo bar'
classNames('foo', { bar: true }); // 'foo bar'
classNames({ 'foo-bar': true }); // 'foo-bar'
classNames({ 'foo-bar': false }); // ''
classNames({ foo: true }, { bar: true }); // 'foo bar'
classNames({ foo: true, bar: true }); // 'foo bar'
classNames(['foo', 'bar']); // 'foo bar'

// 동시에 여러개의 타입으로 받아올 수도 있다.
classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); // 'foo bar baz quux'

// false, null, 0, undefined와 같이 falsy한 값들은 무시된다.
classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // 'bar 1'

✍️ 위와 같이 classnames의 도움을 받지 않을 경우엔 아래처럼 동적으로 클래스 이름을 넣을 수 있겠다.

// size로 medium이 넘어올 경우
function Button({ children, size }) {
 return <button className={['Button', size].join(' ')}>{children}</button>;
} // Button medium

// className={`Button ${size}`} 혹은 이렇게 받아온다.

ex) 예시 ▼

// Button.jsx
function Button({ children, size, color, outline }) {
  return (
    // props로 받아와서 객체 안에 넣음 ▼
    // outline 값이 true 일 때에만 button 에 outline CSS 클래스가 적용된다.
    <button className={classNames('Button', size, color, { outline })}>
      {children}
    </button>
  );
}
// App.js
<div className='buttons'>
  <Button size='large' outline> BUTTON </Button>
  <Button color='pink'>BUTTON</Button> // outline X
  <Button size='small' color='violet' outline> BUTTON </Button>
</div>
// button.scss
$blue: #228be6;
$pink: #ff8787;
$violet: #b197fc;

@mixin button-color($color) { // 2)
  background: $color;
  &:hover {
    background: ligthen($color, 10%); // 색상 10% 밝게 해주는 함수
  }
  &:active {
    background: darken($color, 10%); //  // 색상 10% 어둡게 해주는 함수
  }
  &.outline {
    color: $color;
    background: none;
    border: 1px solid $color;
    &:hover {
      background: $color;
      color: white;
    }
  }
}

.Button {
  color: white;
  font-weight: bold;
  outline: none;
  border-radius: 4px;
  border: none;
  cursor: pointer;

  // 사이즈 관리
  &.large {
    // .button.large 를 의미한다. (선택자1과 선택자2 모두만족)
    height: 3rem;
    padding-left: 1rem;
    padding-right: 1rem;
    font-size: 1.25rem;
  }

  &.medium {
    ...
  }

  &.small {
    ...
  }

  // 색상 관리
  &.blue {
    @include button-color($blue);
  }

  &.pink {
    ...
  }

  &.violet {
    ...
  }

  & + & { // 1)
    margin-left: 1rem;
  }
}
  • 1) & + &  가 의미 하는 것은 .Button + .Button  이다. 만약 함께 있다면 우측에 있는 버튼에 여백을 설정 한 것이다. (제일 좌측은 여백이 그대로인데, 이렇게 나란히 있을 때 사용하기 좋을 것 같다! 😀 )

  • 2) @mixin 반복이 되는 코드는 Sass 의 mixin 이라는 기능을 사용하여 쉽게 재사용 할 수 있다.





3. CSS Module

컴포넌트를 스타일링 할 때 CSS Module 을 사용하면, CSS 클래스가 중첩되는 것을 방지할 수 있다.


CSS와 SCSS import 하기

import './App.css';
import './App.scss';
  • Module을 적용하지 않는다면, 최상단 App.jsx 또는 컴포넌트에서 css, scss파일을 호출한다.
  • 전역적으로 스타일들이 순서만 다르게 들어갈 뿐이므로 스코프가 오염될 수 있다.

이러한 단점을 극복하기 위해서 webpack을 이용해서 스코프가 오염되지 않는 형태로 자동으로 도움을 주는 기능이 추가된 형태의 css 모듈을 사용한다.



CSS 모듈 사용하기

  • webpack 에서 제공하는 css-loader에서 지원이 되며, CRA로 만든 프로젝트일 경우 이미 적용이 되어 있어서 별도로 설치하지 않아도 된다. 😀
  • CRA 로 만든 프로젝트에서 CSS Module 를 사용 할 때에는, CSS 파일의 확장자를 .module.css 로 한다.
import styles from './App.module.css';
import styles from './App.module.scss';
  • css모듈을 사용하면 실제 작성했던 css 코드를 변환을 시킨 후 스타일에 (전역으로) 추가해준다.

  • css 클래스 이름이 만들어지는 과정에서는 파일 경로, 파일 이름, 클래스 이름, 해쉬값 등이 사용 될 수 있다.
    [filename]\_[classname]\_\_[hash] 형식의 고유한 클래스 이름을 자동으로 생성하고 매칭시켜준다. → 이름이 충돌되지 않도록 돕는다.

  • 즉, css-module을 이용하면 클래스명이 충돌하는 일반적인 css단점을 극복할 수 있게 된다.

  • 다음과 같은 상황에서 사용하면 유용하다.
    • 레거시 프로젝트에 리액트를 도입할 때 (기존 프로젝트에 있던 CSS 클래스와 이름이 중복하더라도 스타일이 꼬이지 않게 해준다.)
    • 클래스명 중복을 피하기 위해 CSS 클래스 네이밍 규칙(BEM 등)을 만들기 번거로울 때



styles 살펴보기

CRA - css와 scss Modules Stylesheet 추가하기

  • className 을 설정 할 때에는 styles.name 과 같이 import로 불러온 styles 객체 안에 있는 값을 참조한다.
  • 클래스 이름에 - 가 있다면 styles[class-name] 과 같이 사용한다.
  • 여러개일 경우 ${style.a} ${style.b} 과 같이 작성한다.

✍️ classnames 라이브러리 활용하기

  • 조건부 스타일링을 할 경우 classnames 라이브러리 도움을 받을 수 있다.

  • classnamesbind 기능을 사용하면, 이름을 지정해 줄 때 cx('클래스이름') 과 같은 형식으로 편하게 사용 할 수 있다. 여러개의 CSS 클래스를 사용해야 하거나, 조건부 스타일링에 사용된다.

    // ${styles.one} ${condition ? styles.two : ''} 와 같이 사용하는 것 대신
    
    import classNames from 'classnames/bind';
    const cx = classNames.bind(styles);
    
    cx('one', 'two')
    cx('my-component', {
      condition: true
    })
    cx('my-component', ['another', 'classnames'])

✍️ styles 객체

console.log(styles) 콘솔에 출력해보자.

{
  App: "App_App__B2Ebb"
  App-logo-spin: "App_App-logo-spin__1up6W"
  header: "App_header__fhC8n"
  link: "App_link__kpF6Q"
  logo: "App_logo__7Edbg"
}

위와 같은 객체가 출력되는 것을 볼 수 있다. 🤔
→ 따라서 styles로 부터 얻어낸 값을 사용하기 위해서 JSX문법으로 해당key를 주면 아래처럼 작성해 볼 수 있다.

// 초기 App 컴포넌트에서 css모듈 설정
function App() {
  return (
    <div className={styles.App}>
      <header className={styles.header}>
        <img src={logo} className={styles.logo} alt='logo' />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className={styles.link}
          href='https://reactjs.org'
          target='_blank'
          rel='noopener noreferrer'
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

✍️ global & local

  • CSS Module 을 사용하고 있는 파일에서 클래스 이름을 고유화 하지 않고 전역적 클래스이름을 사용하고 싶을 땐 아래와 같이 사용한다.

    // css
    :global .my-global-name { 
    
    }
    
    // scss
    :global {
      .my-global-name {
    
      }
    }
  • CSS Module 을 사용하지 않는 곳에서 특정 클래스에서만 고유 이름을 만들어서 사용하고 싶다면 아래와 같이 사용한다.

    // css
    :local .make-this-local { 
    
    }
    
    // scss
    :local {
      .make-this-local {
    
      }
    }


✍️ JavaScript에서 CSS를 적용할 때 SCSS를 사용해 보았는데 React에서는 어떻게 적용해야 하는지 궁금했던 점을 알 수 있었다.(CRA 정말 편하다👍)
styles를 통해 CSS를 적용하는 부분이나 classnames 라이브러리를 통해 스타일을 적용하는 부분은 자주 접해보면서 익숙해져야겠다.🧐




reference)
heropy - scss
vlpt-react styling
fastcapmus

profile
기억보단 기록을 ✨

0개의 댓글