벨로퍼트 리액트 - 2-2. CSS Module
CSS Module : CSS 클래스가 중첩되는 것을 방지해준다. 확장자는 .module.css . 컴포넌트에서 해당 파일을 불러오면 내부에 선언된 클래스 이름들이 모두 고유해진다. 이 과정에서 파일 경로, 파일 이름, 클래스 이름, 해쉬값 등이 사용될 수 있다.
클래스 이름에 대하여 고유한 이름들이 만들어지기 때문에 실수로 다른 관계없는 곳에서 이름이 중복되지 않음!
CSS Module을 유용하게 사용할 수 있는 상황
- 레거시 프로젝트에 도입할때 (기존 css와 이름이 중복되어도 스타일이 꼬이지 않음
- CSS 클래스 네이밍 규칙 만들기 귀찮을때
예제) CSS Module을 사용하여 커스텀 체크박스 컴포넌트 만들기
components/CheckBox.js
import React from "react";
function CheckBox({children, checked, ...rest}) { // 기타 값을 input에 전해주기위해 ...rest 사용
return (
<div>
<label>
<input type="checkbox" checked={checked} {...rest} />
<div>{checked ? '체크됨' : '체크 안됨'}</div>
// checked의 boolean 값에 따라 내용이 다르게 나옴. 체크됨(참) 체크 안됨(거짓)
</label>
<span>{children}</span> // 컴포넌트 태그 사이에 넣은 값 조회하기 위해 사용
</div>
);
}
export default CheckBox;
App.js
import React, { useState } from 'react';
import CheckBox from './components/CheckBox';
function App() {
const [check, setCheck] = useState(false); // check의 기본 상태는 false
const onChange = e => {
setCheck(e.target.checked);
// onChange가 실행되면 e.target(이벤트가 발생한 DOM)의 checked를 현재 상태로 받는다
// e.target.checked = e.target이 체크 되었는지 아닌지 반환함
};
return (
<div>
<CheckBox onChange={onChange} checked={check}>
다음 약관에 모두 동의
</CheckBox>
<p>
<b>check: </b>
{check ? 'true' : 'false'}
</p>
</div>
);
}
export default App;
** react-icons 라이브러리 : 아이콘을 컴포넌트 형태로 사용할 수 있는 라이브러리
npm add react-icons
아래와 같은 형식으로 사용
components/CheckBox.module.css
.checkbox {
display: flex;
align-items: center;
}
.checkbox label {
cursor: pointer;
}
/* 실제 input 을 숨기기 위한 코드 */
.checkbox input {
width: 0;
height: 0;
position: absolute;
opacity: 0;
}
.checkbox span {
font-size: 1.125rem;
font-weight: bold;
}
.icon {
display: flex;
align-items: center;
/* 아이콘의 크기는 폰트 사이즈로 조정 가능 */
font-size: 2rem;
margin-right: 0.25rem;
color: #adb5bd;
}
.checked {
color: #339af0;
}
components/CheckBox.js
import React from 'react';
import { MdCheckBox, MdCheckBoxOutlineBlank } from 'react-icons/md';
import styles from './CheckBox.module.css';
function CheckBox({ children, checked, ...rest }) {
return (
<div className={styles.checkbox}>
<label>
<input type="checkbox" checked={checked} {...rest} />
<div className={styles.icon}>
{checked ? (
<MdCheckBox className={styles.checked} />
) : (
<MdCheckBoxOutlineBlank />
)}
</div>
</label>
<span>{children}</span>
</div>
);
}
export default CheckBox;
CSS Module 사용시에는 객체 안에 있는 값을 조회해서 적용해야한다
ex ) styles.icon
클래스 이름에 -(하이픈)이 들어가 있다면 : styles[’bg-blue’]
클래스가 여러개라면 : ${styles.large} ${styles.green}
조건부 스타일링을 한다면 : ${styles.large} ${condition ? styles.warning : ‘’}
⇒ 이러한 번거로움을 해결하기 위해 classnames 라이브러리의 bind 기능 이용
cx(’클래스 이름’) 과 같은 형식으로 사용할 수 있다.
전역 클래스 이름을 사용하고 싶다면
:global .my-global-name {}
css Module 을 사용하지 않는 특정 클래스에서만 고유이름을 만들어서 사용하고싶다면
:local .make-this-local {}
벨로퍼트 리액트 - 2-3. styled-components
styled-components : CSS in JS(JS 안에 CSS 작성) 를 사용하는 라이브러리.
스타일을 입력함과 동시에 해당 스타일을 가진 컴포넌트를 만들 수 있다.
const Circle = styled.div`
width: 5rem;
height: 5rem;
background: ${props => props.color || 'black'}; // props 사용시.
border-radius: 50%;
${props => // props 사용 + 여러줄의 css를 조건부로 보여줄때
props.huge &&
css`
width: 10rem;
height: 10rem;
`}
`;
sass 처럼 유틸 함수를 사용할때는 polished 라이브러리 사용하기
// 색상
background: #228be6;
&:hover {
background: ${lighten(0.1, '#228be6')};
}
&:active {
background: ${darken(0.1, '#228be6')};
}
ThemeProvider 기능 사용해서 색상변수를 전역값으로 설정하기
<ThemeProvider
theme={{
palette: {
blue: '#228be6',
gray: '#495057',
pink: '#f06595'
}
}}
>
<AppBlock>
<Button>BUTTON</Button>
</AppBlock>
</ThemeProvider>
// 색상 조회할때는
${props => {
const selected = props.theme.palette[props.color];
return css`
background: ${selected};
&:hover {
background: ${lighten(0.1, selected)};
}
&:active {
background: ${darken(0.1, selected)};
}
`;
}}