[React] 13. 컴포넌트 스타일링 (2)
1. CSS Module ✍
- CSS Module은
CSS
를 불러와서 사용할 때 크래스 이름을 고유한 값 형태로 만들어 컴포넌트 스타일 클래스 이름이 중첩되는 현상을 방지하는 기술이다.
* 즉, [파일이름]_[클래스이름]_[해시값] 형태로 생성
- 사용 방법은
.module.css
확장자로 파일을 저장하면 CSS Module이 적용된다.
src/CSSModule.module.css
파일을 생성하여 다음과 같이 작성했다.
// CSSModule.module.css
/* 자동으로 고유해지기 때문에 흔히 사용되는 단어 클래스 이름으로 사용 가능*/
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
}
/* 글로벌 CSS를 작성 */
:global .something {
font-weight: 800;
color: aqua;
}
TIP ❗❗
- 위의 클래스는 생성한 스타일을 직접 불러온 컴포넌트 내부에서만 작동한다.
- 만약, 특정 클래스가 웹페이지에서 전역적으로 사용되는 경우는
:global
을 앞에 입력하여 글로벌 CSS임을 명시하면 된다.
- 그 후,
CSS Module
을 사용하는 컴포넌트를 만들기 위해 src/CSSModule.js
파일을 생성하여 다음과 같이 작성했다.
// CSSModule.js
import React from "react";
import styles from './CSSModule.module.css';
const CSSModule = () => {
return (
<div className={styles.wrapper}>
안녕하세요, 저는 <span className="something">CSS Module 입니다.</span>
</div>
);
};
export default CSSModule;
- CSS Module이 적용된 스타일 파일을 불러오면 객체를 전달받게 된다.
- 사용한 클래스
이름
, 해당 이름을 고유화한 값이 키-값
형태로 들어있다.
* 예를 들어, 위의 코드에서 console.log(styles)
를 한다면 다음과 같은 결과가 나온다.
// 👉 결과: { wrapper: "CSSModule_wrapper_1sbdQ" }
- 즉, 지정한 클래스 이름 앞뒤로 파일 이름과 해시값이 붙어있다.
중요 ❗❗
- 고유한 클래스 이름을 사용하려면 클래스를 적용하고 싶은
JSX 엘리먼트
에 className={styles.[클래스 이름]}
형태로 전달하면 된다.
- 반면에,
:global
을 사용하여 전역적으로 선언한 클래스의 경우 그냥 문자열로 넣어 사용한다.
1.1 클래스 두 개 이상 적용하기
- CSS Module을 사용한 클래스 이름을 두 개 이상 적용할 때는 아래와 같은 코드를 사용한다.
//Example
<div className={`${styles.wrapper} ${styles.wrapper2}`}></div>
- 위 코드에서 ES6 문법 템플릿 리터럴을 사용하여 문자열을 합해 주었는데
CSS Module
클래스를 여러 개 사용할 때 템플릿 리터럴
문법을 사용하기 싫으면 아래와 같이 사용하면 된다.
//Example
<div className={[styles.wrapper, styles.wrapper2].join(' ')}</div>
1.2 classnames
- classnames는
CSS 클래스
를 조건부로 설정할 때 유용한 라이브러리
이다.
- 또한, CSS Module을 사용할 때 같이 사용하면 매우 유용하고 다음과 같은 방법으로
라이브러리
를 설치했다.
$ yarn add classnames
- 기본적인 사용법은 다음과 같다.
import classNames from 'classnames';
classNames('one', 'two'); // 👉 'one two'
classNames('one', { two: true }); // 👉 'one two'
classNames('one', { two: false }); // 👉 'one'
classNames('one', ['two', 'three']); // 👉 'one two three'
const myClass = 'hello';
classNames('one', myClass, { myCondition: true }); // 👉 'one hello myCondition'
- 위와 같이 사용할 경우 여러 가지 종류의 파라미터를 조합하여
CSS 클래스
를 설정할 수 있다.
- 즉, 컴포넌트에서
조건부
로 클래스
를 설정하기 편리하다.
* 쉽게 말해서, 아래의 코드 처럼 props
값에 따라 스타일을 설정하기 쉬워진다.
const MyComponent = ({ highlighted, theme }) => (
<div className={classNames('Mycomponent', {highlighted}, theme)}>Hello</div>
);
- 이렇게 작성할 경우, 위의 엘리먼트 클래스에
highlighted
값이 true
이면 highlighted
클래스가 적용되고, false
이면 적용되지 않는다.
- 반면에
theme
으로 전달받는 문자열은 내용 그대로 클래스에 적용된다.
1.3 Sass와 함께 사용하기
- Sass를 사용할 때도
.module.scss
확장자를 사용하면 CSS Module
로 사용할 수 있다.
src/CSSModule.module.scss
파일을 생성하여 다음과 같이 작성했다.
//CSSModule.module.scss
/* 자동으로 고유해지기 때문에 흔히 사용되는 단어 클래스 이름으로 사용 가능*/
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
&.inverted {
// inverted가 .wrapper와 함께 사용되면 적용
color: black;
background: white;
border: 1px solid black;
}
}
/* 글로벌 CSS를 작성 */
:global {
// :global {}로 감싸기
.something {
font-weight: 800;
color: aqua;
}
// 여기에 다른 클래스 추가 가능
}
- 그 후,
CSSModule.js
상단에서도 import
했던 방법 그대로 불러와 사용하면 된다.
import styles from './CSSModule.module.scss';
유용한 TIP ❗❗
- CSS Module이 아닌 파일에서 CSS Module을 사용하기 위해선
글로벌 클래스
를 정의할 때 사용했던 것처럼 CSS Module이 아닌 일반 .css/.scss
파일에서 :local
을 사용하면 된다.
2. styled-components
- 컴포넌트 스타일링을
자바스크립트
파일 안에 스타일을 선언하는 방법을 CSS-in-JS
라고 한다.
- 이와 관련된
라이브러리
는 너무 많아서 CSS-in-JS를 참고하자.✔
- 현재 styled-components를 대체할 수 있는 라이브러리는
emotion
이 대표적이다.
* emotion
을 설치하는 방법은 아래와 같다.
$ yarn add styled-components
- styled-components를 사용하면
자바스크립트
파일 하나에 스타일까지 작성할수 있기때문에 .css
, .scss
확장자를 가진 스타일 파일
을 따로 만들지 않아도 된다.
src/StyledComponent.js
파일을 생성하여 다음과 같이 작성했다.
//StyledComponent.js
import React from "react";
import styled, { css } from 'styled-components';
const Box = styled.div`
/* props로 넣어준 값을 직접 전달 */
background: ${props => props.color || 'blue'};
padding: 1rem;
display: flex;
`;
const Button = styled.button`
background: white;
color: black;
border-radius: 4px;
padding: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: 1rem;
font-weight: 600;
/* & 문자를 사용하여 Sass처럼 자기 자신 선택 가능 */
&:hover {
background: rgba(255, 255, 255, 0.9);
}
/* 아래 코드는 inverted 값이 true일 때 특정 스타일 부여 */
${props =>
props.inverted &&
css`
background: none;
border: 2px solid white;
color: white;
&:hover {
background: white;
color: black;
}
`};
& + button {
margin-left: 1rem;
}
`;
const StyledComponent = () => {
return (
<Box color="black">
<Button>안녕하세요.</Button>
<Button inverted={true}>테두리만</Button>
</Box>
);
};
export default StyledComponent;
CSS
를 불러와서 사용할 때 크래스 이름을 고유한 값 형태로 만들어 컴포넌트 스타일 클래스 이름이 중첩되는 현상을 방지하는 기술이다.* 즉, [파일이름]_[클래스이름]_[해시값] 형태로 생성
.module.css
확장자로 파일을 저장하면 CSS Module이 적용된다.src/CSSModule.module.css
파일을 생성하여 다음과 같이 작성했다.// CSSModule.module.css
/* 자동으로 고유해지기 때문에 흔히 사용되는 단어 클래스 이름으로 사용 가능*/
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
}
/* 글로벌 CSS를 작성 */
:global .something {
font-weight: 800;
color: aqua;
}
- 위의 클래스는 생성한 스타일을 직접 불러온 컴포넌트 내부에서만 작동한다.
- 만약, 특정 클래스가 웹페이지에서 전역적으로 사용되는 경우는
:global
을 앞에 입력하여 글로벌 CSS임을 명시하면 된다.
CSS Module
을 사용하는 컴포넌트를 만들기 위해 src/CSSModule.js
파일을 생성하여 다음과 같이 작성했다.// CSSModule.js
import React from "react";
import styles from './CSSModule.module.css';
const CSSModule = () => {
return (
<div className={styles.wrapper}>
안녕하세요, 저는 <span className="something">CSS Module 입니다.</span>
</div>
);
};
export default CSSModule;
이름
, 해당 이름을 고유화한 값이 키-값
형태로 들어있다.* 예를 들어, 위의 코드에서
console.log(styles)
를 한다면 다음과 같은 결과가 나온다.// 👉 결과: { wrapper: "CSSModule_wrapper_1sbdQ" }
JSX 엘리먼트
에 className={styles.[클래스 이름]}
형태로 전달하면 된다.:global
을 사용하여 전역적으로 선언한 클래스의 경우 그냥 문자열로 넣어 사용한다.//Example
<div className={`${styles.wrapper} ${styles.wrapper2}`}></div>
CSS Module
클래스를 여러 개 사용할 때 템플릿 리터럴
문법을 사용하기 싫으면 아래와 같이 사용하면 된다.//Example
<div className={[styles.wrapper, styles.wrapper2].join(' ')}</div>
CSS 클래스
를 조건부로 설정할 때 유용한 라이브러리
이다.라이브러리
를 설치했다.$ yarn add classnames
import classNames from 'classnames';
classNames('one', 'two'); // 👉 'one two'
classNames('one', { two: true }); // 👉 'one two'
classNames('one', { two: false }); // 👉 'one'
classNames('one', ['two', 'three']); // 👉 'one two three'
const myClass = 'hello';
classNames('one', myClass, { myCondition: true }); // 👉 'one hello myCondition'
CSS 클래스
를 설정할 수 있다.조건부
로 클래스
를 설정하기 편리하다.* 쉽게 말해서, 아래의 코드 처럼
props
값에 따라 스타일을 설정하기 쉬워진다.const MyComponent = ({ highlighted, theme }) => (
<div className={classNames('Mycomponent', {highlighted}, theme)}>Hello</div>
);
highlighted
값이 true
이면 highlighted
클래스가 적용되고, false
이면 적용되지 않는다.theme
으로 전달받는 문자열은 내용 그대로 클래스에 적용된다..module.scss
확장자를 사용하면 CSS Module
로 사용할 수 있다.src/CSSModule.module.scss
파일을 생성하여 다음과 같이 작성했다.//CSSModule.module.scss
/* 자동으로 고유해지기 때문에 흔히 사용되는 단어 클래스 이름으로 사용 가능*/
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
&.inverted {
// inverted가 .wrapper와 함께 사용되면 적용
color: black;
background: white;
border: 1px solid black;
}
}
/* 글로벌 CSS를 작성 */
:global {
// :global {}로 감싸기
.something {
font-weight: 800;
color: aqua;
}
// 여기에 다른 클래스 추가 가능
}
CSSModule.js
상단에서도 import
했던 방법 그대로 불러와 사용하면 된다.import styles from './CSSModule.module.scss';
글로벌 클래스
를 정의할 때 사용했던 것처럼 CSS Module이 아닌 일반 .css/.scss
파일에서 :local
을 사용하면 된다.- 컴포넌트 스타일링을
자바스크립트
파일 안에 스타일을 선언하는 방법을CSS-in-JS
라고 한다. - 이와 관련된
라이브러리
는 너무 많아서 CSS-in-JS를 참고하자.✔ - 현재 styled-components를 대체할 수 있는 라이브러리는
emotion
이 대표적이다.
*emotion
을 설치하는 방법은 아래와 같다.
$ yarn add styled-components
- styled-components를 사용하면
자바스크립트
파일 하나에 스타일까지 작성할수 있기때문에.css
,.scss
확장자를 가진스타일 파일
을 따로 만들지 않아도 된다. src/StyledComponent.js
파일을 생성하여 다음과 같이 작성했다.
//StyledComponent.js
import React from "react";
import styled, { css } from 'styled-components';
const Box = styled.div`
/* props로 넣어준 값을 직접 전달 */
background: ${props => props.color || 'blue'};
padding: 1rem;
display: flex;
`;
const Button = styled.button`
background: white;
color: black;
border-radius: 4px;
padding: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: 1rem;
font-weight: 600;
/* & 문자를 사용하여 Sass처럼 자기 자신 선택 가능 */
&:hover {
background: rgba(255, 255, 255, 0.9);
}
/* 아래 코드는 inverted 값이 true일 때 특정 스타일 부여 */
${props =>
props.inverted &&
css`
background: none;
border: 2px solid white;
color: white;
&:hover {
background: white;
color: black;
}
`};
& + button {
margin-left: 1rem;
}
`;
const StyledComponent = () => {
return (
<Box color="black">
<Button>안녕하세요.</Button>
<Button inverted={true}>테두리만</Button>
</Box>
);
};
export default StyledComponent;
- styled-components와 일반 classNames를 사용하는
CSS/Sass
를 비교했을 때,props
값으로 전달해 스타일을 적용하는게 편리한 것 같다.✔
TIP 🌟
- VS Code를 사용할 때
styled-components
를 작성한 스타일이문자열
로 인식해서 코드 신택스 하이라이팅이 이루어지지 않는다. - Vs Code의 마켓플레이스(확장프로그램)에서
vscode-styled-components
를 검색하여 설치하면 해결 가능❗❗
2.1 Tagged 템플릿 리터럴
- 앞서 작성한 코드를 보면 `를 사용하여 스타일을 작성했다.
* `를 사용하는 문법을 Tagged 템플릿 리터럴 이라고 한다. - 이해를 돕기 위해 아래의 예제를 살펴보자.
`hello ${{foo: 'bar'}} ${() => 'world'}!`
// 👉 결과: "hello [object Object] () => 'world'!"
- 즉, 템플릿에
객체
를 넣거나함수
를 넣으면 형태를 잃어 버리게 된다. - 이를 해결하기 위해선
함수
를 작성하고 나서 해당함수
뒤에 템플릿 리터럴을 넣어준다면 온전한 값을 추출할 수 있다.
function tagged(...agrs) {
console.log(args);
}
tagged`hello ${{foo: 'bar'}} ${() => 'world'}!`
- styled-components는 이러한 속성을 사용하여
컴포넌트
의props
를 스타일 쪽에서 쉽게 조회할 수 있도록 한다.
2.2 스타일링된 엘리먼트 만들기
- styled-components를 사용하여 스타일링된
엘리먼트
를 만들 때는 컴포넌트 파일의 상단에서 styled를 불러오고,styled.태그명
을 구분하여 사용해야 한다.
//Example
import styled from 'styled-components';
const MyComponent = styled.div`
font-size: 2rem;
`;
- styled.div 뒤에
Tagged 템플릿 리터럴 문법
을 통해 스타일을 넣어주면, 해당 스타일이 적용된div
로 이루어진 컴포넌트가 생성된다. - 추가로, 사용할
태그명
이 유동적이거나특정 컴포넌트
자체에 스타일링 하고 싶다면 다음과 같은 형태로 사용하면 된다.
// 태그 타입을 styled 함수의 인자로 전달
const MyInput = styled('input')`
background: gray;
`
// 컴포넌트를 값으로 넣을 때
const StyledLing = styled(Link)`
color: blue;
`
2.3 스타일에서 props 조회하기
- styled-components를 사용하면 스타일 쪽에서
컴포넌트
에게 전달된props
값을 참조할 수 있는데2 절
에서 사용한StyledComponent.js
의 일부 코드를 통해 살펴보자.
//StyledComponent.js
const Box = styled.div`
/* props로 넣어준 값을 직접 전달 */
background: ${props => props.color || 'blue'};
padding: 1rem;
display: flex;
`;
- 위의 코드를 보면
background
값에props
를 조회해서props.color
의 값을 사용하고 있다. - 그리고
color
값이 주어지지 않을 때는blue
를 기본 색상으로 설정하는 코드이다.
2.4 props에 따른 조건부 스타일링
- 일반
CSS 클래스
를 사용하여 조건부 스타일링을 할 때는className
을 사용해야 한다. - styled-components에서는 조건부 스타일링을
props
로 처리할 수 있다. 2 절
에서 사용한StyledComponent.js
의 일부 코드를 통해 살펴보자.
//StyledComponent.js
const Button = styled.button`
background: white;
color: black;
border-radius: 4px;
padding: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: 1rem;
font-weight: 600;
/* & 문자를 사용하여 Sass처럼 자기 자신 선택 가능 */
&:hover {
background: rgba(255, 255, 255, 0.9);
}
/* 아래 코드는 inverted 값이 true일 때 특정 스타일 부여 */
${props =>
props.inverted &&
css`
background: none;
border: 2px solid white;
color: white;
&:hover {
background: white;
color: black;
}
`};
& + button {
margin-left: 1rem;
}
`;
- 위의 코드로 만든
컴포넌트
는 다음과 같이props
를 사용하여 서로 다른 스타일을 적용할 수 있다.
<Button>안녕하세요.</Button>
<Button inverted={true}>테두리만</Button>
- 여기서 중요한 점은
props
에 따라 여러 스타일 코드를 작성해야 하면 반드시CSS
로 감싸 주어서Tagged 템플릿 리터럴
을 사용해야 한다.❗❗
2.5 반응형 디자인
- 저번에 실습했던 브라우저의
가로 크기
에 따라 다른 스타일을 적용하기 위해선일반 CSS
와 똑같이media 쿼리
를 사용하면 된다. src/MediaStyledComponent.js
를 생성하여src/StyledComponent.js
파일의Box
부분만 다음과 같이 수정했다.
//MediaStyledComponent.js
const Box = styled.div`
/* props로 넣어준 값을 직접 전달 */
background: ${props => props.color || 'blue'};
padding: 1rem;
display: flex;
/* 기본적으로 가로 크기 1024px에 가운데 정렬을 하고
가로 크기가 작아짐에 따라 크기를 줄이고
768px 미만이 되면 꽉 채운다. */
width: 1024px;
margin: 0 auto;
@media (max-width: 1024px) {
width: 768px;
}
@media (max-width: 768px) {
width: 100%;
}
`;
(...)
- 위의 코드를 사용하면 정상적으로 웹 브라우저 크기에 따라 컴포넌트 크기가 바뀌는 것을 확인할 수 있다.
- 하지만, 여러
컴포넌트
에서 반복해야 할 경우에 이 작업을 함수화하여 간편하게 사용할 수 있다.
* styled-components 메뉴얼에서 제공하는 유틸 함수는 아래와 같다.
const sizes = {
desktop: 1024,
tablet: 768
};
// 위에 있는 size 객체에 따라 자동으로 media 쿼리 함수 생성
// 참조: https://www.styled-components.com/docs/advanced#media-templates
const media = Object.keys(sizes).reduce((acc, label) => {
acc[label] = (...args) => css`
@media (max-width: ${sizes[label] / 16}em) {
${css(...args)};
}
`;
return acc;
}, {});
// 사용법
👉 ${media.desktop`width: 768px;`}
👉 ${media.tablet`width: 100%;`}
- 위의 방법을 모듈화하여 여기저기서 불러와서 설정하면 모든
컴포넌트
에media
를 선언할 필요가 없다.
end
Author And Source
이 문제에 관하여([React] 13. 컴포넌트 스타일링 (2)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@daekyeong/React-13.-컴포넌트-스타일링-2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)