컴포넌트 스타일링 방식
리액트에서 컴포넌트를 스타일링할 때는 다양한 방식을 사용할 수 있습니다.
일반 CSS
프로젝트는 일반 CSS 방식으로 만들어져 있습니다.
- CSS를 작성할 때 가장 중요한 점은 CSS 클래스를 중복되지 않게 만드는 것입니다.
이름 짓는 규칙
프로젝트에 자동 생성된 App.css를 읽어 보면 클래스 이름이 컴포넌트 이름-클래스 형태로 지어져 있습니다.
(예 : App-header) 클래스 이름에 컴포넌트 이름을 포함시켜 다른 컴포넌트에서 실수로 중복되는 클래스를 만들어 사용하는 것을 방지합니다.
비슷한 방식으로 BEM 네이밍 방식도 있습니다. BEM 네이밍은 CSS 방법론 중 하나로 해당 클래스가 어디에서 어떤 용도로 사용되는지 명확하게 작성합니다. (예: .card_title-primary)
CSS Selector
CSS Selector를 사용하면 CSS 클래스가 특정 클래스 내부에 있는 경우에만 스타일을 적용합니다.
Sass 사용하기
Sass(Syntactically Awesome Style Sheets)는 CSS 전처리기로 스타일 코드의 재활용성을 높여주고 복잡한 작업을 쉽게하여 가독성을 높여 줍니다.
Sass는 두 가지 확장자 .sass와 .scss를 지원합니다.
1 | $font-stack: Helvetica, sans-serif |
1 | $font-stack: Helvetica, sans-serif; |
.sass 확장자는 중괄호{}와 세미콜론;을 사용하지 않습니다.
- 또한 Sass에서는 믹스인 기능을 사용하여 재사용되는 스타일 블록을 함수처럼 사용할 수 있습니다.
1 | // 변수 사용하기 |
함수 분리하기
Sass 변수 및 믹스인은 다른 파일로 분리하여 작성한 뒤 필요한 파일에서 불러와 여러 파일에 적용시킬 수 있습니다.
1 | // 변수 사용하기 |
선언한 변수 파일과 믹스인을 따로 빼네어 utils.scss 파일에 저장했습니다.
다른 파일에서 불러올 때는 @import 구문을 사용하여 불러오면 됩니다.
node_modules에서 라이브러리 불러오기
Sass의 장점 중 하나는 라이브러리를 쉽게 불러와서 사용할 수 있다는 점입니다.
위와 같이 상대 경로를 사용하여 node_modules까지 들어가서 불러올 필요없이 물결 문자(~) 을 사용하여 불러올수 있습니다.
물결 문자(~)를 사용하면 자동으로 node_modules에서 라이브러리 디렉터리를 탐지하여 스타일을 불러옵니다.
CSS Module
CSS Module은 CSS를 불러와서 사용할 때 클래스 이름을 고유한 값으로 자동으로 만들어 컴포넌트 스타일 클래스 이름이 중첩되는 현상을 방지해 주는 기술입니다.
[파일 이름]_[클래스 이름]_[해시값]
형태로 만듭니다.
create-react-app v2 버전 이상 부터 .module.css 확장자로 파일을 저장하기만 하면 CSS Module이 적용됩니다.
CSSModule.module.css라는 파일을 만들어 보겠습니다.
1 | /* 자동으로 고유해질 것이므로 흔히 사용되는 단어를 클래스 이름으로 마음대로 사용가능*/ |
CSS Module이 적용된 스타일을 불러오면 객체를 전달받게 되는데 CSS Module에서 사용한 클래스 이름이 고유화된 값으로 들어있습니다.
지정해준 클래스 이름 앞뒤로 파일 이름(CSSModule)과 해쉬값(1SbdQ)이 붙은 형태입니다.
이 고유한 클래스 이름을 사용하는 리엑트 컴포넌트를 작성해 보겠습니다.
1 | import React from 'react'; |
위와 같이
고유한 클래스 이름을 사용하려면 클래스를 적용하고 싶은 JSX 엘리먼트에
className={styles.[클래스 이름]}
형태로 전달.:global을 사용하여 전역적으로 선언한 클래스의 경우 일반적으로 사용하던 방법과 똑같이 그냥 클래스이름을 넣어주면됩니다.
className="something"
클래스 이름 두 개 이상 적용
CSS Module로 만든 클래스 이름을 두 개 이상 적용할 때
ES6의 문법 템플릿 리터럴을 사용하여 문자열을 합침으로 간단히 처리할 수 있습니다.
1 | // CSSModule.module.css |
템플릿 리터럴 문법으로 작성하고 싶지 않다면 다음과 같은 방식도 있습니다.
classnames 라이브러리
classnames 라이브러리는 CSS 클래스를 조건부로 설정할 때 매우 유용한 라이브러리입니다.
npm으로 설치 시 : npm install classnames
yarn으로 설치 시 : yarn add classnames
classnames의 기본적인 사용법을 살펴봅니다.
1 | import classNames from 'classnames'; |
이런 식으로 여러 가지 종류의 파라미터를 조합해 CSS 클래스를 설정할 수 있기 때문에 컴포넌트에서 조건부로 클래스를 설정할 때 매우 편합니다. 예를 들어 props 값에 따라 다른 스타일을 주기 편합니다.
1 | // classnames 등의 라이브러리 도움없이 작성한다면 |
classnames 라이브러리 사용 시 엘리먼트의 클래스에 highlighted 값이 true이면 highlighted 클래스가 적용되고, false이면 적용되지 않습니다. 추가로 theme으로 전달받는 문자열은 내용 그대로 클래스에 적용됩니다.
- classnames 라이브러리는 CSS Module과 함께 사용하면 CSS Module 사용이 훨씬 쉬워집니다.
classnames에 내장되어 있는 bind
함수를 사용하면 클래스를 넣어 줄 때마다 styles.[클래스 이름]
형태를 사용할 필요가 없습니다.
사전에 미리 styles에서 받아 온 후 사용하게 설정해 주고 cx('클래스 이름1', '클래스 이름2')
형태로 사용할 수 있습니다.
1 | import React from 'react'; |
classnames의 bind를 사용하여 CSS Module을 사용할 때 클래스를 여러 개 설정하거나, 조건부로 클래스를 설정할 때 편리하게 작성할 수 있습니다.
styled-components
컴포넌트 스타일링 중 자바스크립트 파일 안에 스타일을 선언하는 방식을 CSS-in-JS
라고 부릅니다.
- CSS-in-JS 라이브러리 종류 (https://github.com/MicheleBertoli/css-in-js)
styled-components
는 ‘CSS-in-JS’ 라이브러리 중에서 개발자들이 가장 선호하는 라이브러리입니다.
npm 으로 설치 시 : npm i styled-components
yarn 으로 설치 시 : yarn add styled-components
styled-components를 사용하면 자바스크립트 파일 하나에 스타일까지 작성할 수 있기 때문에
별도의 스타일 파일을 만들지 않아도 된다는 이점이 있습니다.
styled-components를 사용한 예제 코드를 작성해 보겠습니다.
1 | import React from 'react'; |
styled-components의 가장 큰 장점은 props 값으로 전달해 주는 값을 쉽게 스타일에 적용할 수 있다는 것입니다.
Tagged 템플릿 리터럴
스타일을 작성할 때 ` 을 사용하여 만든 문자열에 스타일 정보를 넣어 주었습니다.
여기서 사용한 문법을 Tagged 템플릿 리터럴 이라고 부릅니다.
CSS Module을 배울 때 나온 일반 템플릿 리터럴과 다른 점은 템플릿 안에 자바스크립트 객체나 함수를 전달 할 때 리터럴 안에 넣어준 값을 알아낼 수 있다는 것입니다.
위 코드는 [object Object] 이런식으로 문자열로 들어가게되면서 형태를 잃어버리게 되는데요,
만약에 함수를 다음과 같이 만들어서 사용하면 이 템플릿 리터럴 안에 넣어준 값들을 온전히 알아낼 수 있게 됩니다.
1 | function tagged(...args) { |
styled-components는 이러한 속성을 사용하여 styled-components로 만든 컴포넌트의 props를 스타일 쪽에서 쉽게 조회할 수 있게 해줍니다.
스타일링 된 엘리먼트 만들기
스타일링 된 엘리먼트를 만들 땐, 상단에서 styled 를 불러오고 styled.태그명 을 사용하여 구현합니다:
이렇게 styled.div
뒤에 Tagged 템플릿 리터럴 문법을 통해 스타일을 넣어 주면,
해당 스타일이 적용된 div로 이루어진 리액트 컴포넌트가 생성됩니다.
그래서 나중에 <MyComponent>
Hello</MyComponent>
와 같은 형태로 사용할 수 있습니다.
.div
자리에 button 이던, input 이던, 원하는걸 넣으시면 됩니다.
하지만, 만약에 보여줘야 할 태그 형식이 유동적이거나,
특정 컴포넌트에 스타일링을 해야 하는 상황이라면 다음과 같은 형태로 구현 할 수 있습니다
1 | // 문자열로 styled 의 인자로 전달 |
스타일에서 props 조회하기
styled-components를 사용하면 스타일링 한 컴포넌트에 전달하는 props 값을 스타일쪽에서 그대로 사용할 수 있습니다.
1 | const Box = styled.div` |
background 값에 props를 조회해서 props.color의 값을 사용하게 하고 color 값이 주어지지 않았을 때는 blue를 기본 색상으로 설정했습니다.
이렇게 만들어진 코드는 JSX에서 사용될 때 다음과 같이 color 값을 props로 사용할 수 있습니다.
props 에 따른 조건부 스타일링
일반 CSS 클래스를 사용했더라면 주로 클래스이름으로 조건부 스타일링을 해왔었을텐데요,
styled-components 에서는 그냥 props 로도 처리 가능합니다.
1 | import styled, { css } from 'styled-components'; |
이렇게 만든 컴포넌트는 다음과 같이 props를 사용하여 서로 다른 스타일을 적용할 수 있습니다.
CSS를 사용하지 않고 다음과 같이 바로 문자열을 넣어도 작동하기는 합니다.
1 | ${props => |
이렇게 CSS를 제외하고 작성하면 Tagged 템플릿 리터럴이 아니기 때문에 함수를 받아 사용하지 못해 해당 부분에서는 props 값을 사용하지 못합니다.
반응형 디자인
styled-components를 사용할 때 반응형 디자인을 어떻게 하는지 알아봅니다.
우선 브라우저의 가로 크기에 따라 다른 스타일을 적용하기 위해선 일반 CSS를 사용할 때와 똑같이 media 쿼리(query)를 사용하면 됩니다.
1 | const Box = styled.div` |
일반 CSS에서와 큰차이가 없습니다.
만약 여러 컴포넌트에서 이작업을 반복해야 한다면 함수화하여 간편하게 사용할 수 있습니다.
1 | import React from 'react'; |