React
20210729 React style 01: REACT CSS(classnames 라이브러리), SCSS(open-color, include-media 라이브러리), CSS Module, Styled-components
React Style 01
📄 주요 사항 정리
리액트의 스타일 방식은 여러가지가 존재 한다.
- 일반적인 CSS
- Sass
- CSS Module
- styled-components
CSS
작은 규모의 프로젝트의 경우에는 기존의 CSS 스타일링을 고수하여 사용하여도 좋음
- CSS 클래스를 중복되지 않게 만드는 것이 제일 중요함
- REACT에서 추천하는 형태 :
컴포넌트 이름-클래스
형태 - BEM :
Block__Element--Modifier
형태- Block : 큰 독립적인 형태 (화면을 구성하는 component 단위의 느낌)
- Element : Block을 구성하는 작은 단위
- Modifier : Block 또는 Element의 속성(특성, 외관 상태를 변화시키는 것)을 담당함
- CSS Selector(CSS 선택자) : 선택자의 위계 질서를 통해서 특정 부분을 구체적으로 가르켜 스타일링 하는 방식
- 컴포넌트 최상위 HTML 요소 : 컴포넌트의 이름으로 클래스 이름 설정 (파스칼 케이스)
- 컴포넌트 내부 요소 : 태그이름, 내부 요소의 이름으로 클래스 이름 설정 (소문자)
Sass
- Sass(Syntactically Awesome Style Sheets)
- CSS 전처리기
- 코드 재활용성 향상
- 코드 가독성 향상
- 유지 보수 향상
- CRA v2 버전 부터 React에 별도 추가 설정 없이 Sass 사용 가능
- .scss , .sass 두 가지 확장자 지원
- Component 별로 SCSS를 만들어 해당 Component에 import하여 사용함
utils.scss
: utils 함수 SCSS를 만들어서 Sass 변수 및 믹스인만 따로 관리하여 다른 곳에서@import
하여 사용- sass-loader 설정 커스터 마이징
- cra에서 npm run eject 해서 사용 함(eject 하기전 최초 commit 이있어야 eject가 허용 됨)
- eject 후 webpack.config.js의 sassRegex 설정 부분으로 가기
- sass 파일내의 @import root 경로 변경
- sass 파일 생성시 기본 코드 설정
// webpack.config.js
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders(
{
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
}
).concat({
loader: require.resolve('sass-loader'),
options: {
sassOptions: {
includePaths: [paths.src + '/styles']
// sass 파일의 import root 경로로 styles 폴더를 설정 함
},
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
prependData: `@import 'utils';`
// sass 파일 생성시 보이진 않지만 기본적인 코드 작성 (주로, 기본 import 설정이 들어가는 듯 함)
}
}),
sideEffects: true,
},
open-color, include-media 라이브러리 (Sass 용)
open-color
: 여러가지 색깔을 단계적으로 나누어 고른 색을 사용할 수 있게 해주는 색상 팔레트include-media
: 반응형 디자인을 쉽게 만들어주는 라이브러리 (특정 필셀 또는, phone, tablet, pc 등의 사이즈를 조건으로 스타일을 지정해 줄 수 있음)npm i open-color include-media
- sass 파일에 라이브러리를 @import하여 사용하는 경우 경로를 모두 작성(node_modules/library/...)할 필요 없이
~
로 시작 하면 편하게 @import 할 수 있음
@import "~include-media/dist/include-media";
@import "~open-color/open-color";
CSS Module
파일이름_클래스이름__해시값
형태로 자동으로 만들어서 컴포넌트 스타일 클래스 이름이 중첩되는 현상 방지 (고유성 고민 필요 없음)- CRA v2 부터 따로 설정 없이 가능 함
/*Component.module.css*/
.wrapper {
background: black;
color: white;
}
.inverted {
color: black;
background: white;
}
:global {
/*CSS module에서 글로벌 CSS를 하는 경우*/
.something {
}
}
import React from "react";
import styles from "./Component.module.css";
const Component = () => {
return <div className={`${styles.wrapper} ${styles.inverted}`}>Element</div>;
};
export default Component;
/*
console.log(styles)
{
wrapper: "Component_wrapper__1SbdQ",
inverted: "Compnent_inverted_2BdiK"
}
*/
classnames 라이브러리
- CSS 클래스를 조건부로 설정할 때 유용함
npm i classnames
- trusy 한 값의 이름을 className으로 그대로 들어가게 하고 falsy 값의 이름은 들어가지 않게 함
- 객체를 제공하는 경우 해당 프로퍼티의 값이 trusy 한 경우의 프로퍼티 이름을 className으로 제공함(여러개도 가능함)
import classNames from "classnames";
classNames("one", { two: true, three: false, four: true }); // one two four
- CSS Module과 같이 사용하는 경우, bind를 사용하여 css module과 classnames를 연결하여 편하게 사용할 수 있음
import classNames from "classnames";
import styles from "./Component.modules.css";
const cx = classNames.bind(styles);
cx("wrapper", "inverted");
// cx 함수를 기존에 className을 사용하듯이 사용하면 되고, 굳이 `styles.프로퍼티`로 넣을 필요 없음
styled-components
- JS 파일 안에 스타일을 선언하는 방식인 CSS-in-JS 방식 중에 하나가 styled-components 임
- JS 단의 props를 style에서 참조 할수 있음
- JS의 문법도 사용이 가능해서 여러 조건부 스타일링이 가능 함
- Tagged 템플릿 리터럴 사용
- 일반 템플릿과 다르게 함수 뒤에
` `
백틱을 바로 붙여 함수의 인자를 제공함 - 일반 템플릿과 다르게 템플릿(
${...}
) 안에 있는 코드를 평가하지 않고 온전히 추출 함
- 일반 템플릿과 다르게 함수 뒤에
vscode-styled-components
vscode 익스텐션을 활용하면, 편집기에 Tagged 템플릿 리터럴 부분의 코드의 하이라이팅이 제공 됨
import styled, {css} from 'styled-components'
const Component = () => {
// 컴포넌트 안에서 사용되는 Element 이름과 해당 Element 종류 설정
const MyInput = styled.input`
background: gray;
`
// 컴포넌트 안에서 사용되는 Element 종류를 유동적으로 변경 가능함
const MyDiv = styled('div')`
color: blue;
`
// 컴포넌트 자체를 스타일을 지정할 종류로서 지정 가능함
const Unknown = 'button'
const MyUnknown = styled(Unknown)`
color: pink;
`
// 지정한 Element 자체의 Prop을 받아서 유동적으로 style 값 변경 가능 (prop 참조가 가능해 짐)
const PropDiv = styled.div`
background: ${props => props.color || 'blue'}
`
// 자신 컴포넌트를 참조할 수 있는 &를 사용 할 수 있음 style 값이 아니라 prop을 받아 조건부 style을 구현할 수 있음
// 여러줄의 스타일 코드를 유동적으로 추가시에는 css를 받아와 붙여 태그드 템플릿 구조로 만들어 주어야 함
const PropButton = styled.button`
background: white;
&:hover {
background: gray;
}
${props => props.inverted && css`
background: yellow;
`}
`
return (
<>
<MyInput />
<MyDiv />
<MyUnknown/>
<PropDiv color={"red"} />
<PropButton inverted={true}/>
)
}
- styled-component의 반응형 디자인은 media 쿼리를 사용함 (
@media()
)
import styled {css} from 'styled-components'
const sizes = {
desktop: 1024,
tablet: 768
}
const media = Object.keys(sizes).reduce((acc, label) => {
acc[label] = (...args) => css`
@media (max-width: ${sizes[label]}/ 16em) {
${css(...args)}
}
`;
return acc;
},{})
const Box = styled.div`
${media.desktop`width: 768px;`}
${media.tablet`width: 100%`}
`