일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 컬러구성
- react
- 비동기처리
- 웹
- 리덕스
- 자동반영
- typescript
- Git
- 가상회선교환
- list.map
- merge
- await
- 공부
- pull
- 리사이클러뷰
- createPortal
- async
- 리액트를 다루는 기술
- 리액트
- javascript
- redux
- CSS
- equalityFn
- rebase
- useState
- Kotlin
- useCallback
- list
- hot Reloading
- php문법
- Today
- Total
공부블로그
9강 컴포넌트 스타일링 본문
리액트에서 컴포넌트를 스타일링할 때는 다음 방식들을 사용한다.
- 일반 css : 컴포넌트를 스타일링하는 가장 일반적인 방식
- Sass : 자주 사용되는 css 전처리기 중 하나로, 확장된 css 문법을 사용하여 css 코드를 더욱 쉽게 작성할 수 있다.
- CSS Module : 스타일링을 작성할 때 css 클래스가 다른 css클래스의 이름과 절대 충돌하지 않도록 파일마다 고유한 이름을 자동으로 생성해 주는 옵션
- styled-components : 스타일을 자바스크립트 파일에 내장시키는 방식으로 스타일을 작성함과 동시에 해당 스타일이 적용된 컴포넌트를 만들 수 있게 해준다.
9. 1 ) 가장 흔한 방식, 일반 CSS
프로젝트는 일반 css방식으로 만들어져 있다. 소규모 프로젝트를 개발하고 있다면 기본 css 시스템을 사용하는 것만으로도 충분하다.
css를 작성할 때 가장 중요한 점은 css 클래스를 중복되지 않게 만드는 것이다. 이를 방지하기 위한 방법으로는 이름을 지을 때 특별한 규칙을 이용하여 짓는 것과 CSS Selector를 활용하는 것이 있다.
9. 1. 1 ) 이름 짓는 규칙
예를 들어 App-header처럼 '컴포넌트 이름 - 클래스' 형태로 이름을 지으면 다른 컴포넌트에서 실수로 중복되는 클래스를 만드는 것을 방지할 수 있다.
비슷한 방식으로 해당 클래스가 어디에서 어떤 용도로 사용되는지 명확하게 작성하는 방식인 BEM네이밍도 있다 ( 예: .card_title-primary )
9. 1. 2 ) CSS Selector
CSS Selctor를 사용하면 CSS클래스가 특정 클래스 내부에 있는 경우에만 스타일을 적용할 수 있다.
App. css
/*.App안에 들어있는 .logo에 스타일을 적용 (App.js에서 className='logo'라고 작성)*/
.App .logo {
animation: App-logo-spin infinite 20s linear;
height: 40vmin;
}
/*.App안에 들어있는 header, header 클래스가 아닌 header 태그 자체에 스타일을 적용하므로 .생략 */
.App header {
background-color: #282c34;
...
color: white;
}
.App a {
/* App 안에 들어있는 a 태그 */
color: #61dafb;
}
App. js
function App() {
return (
<div className="App">
<header> //header태그
<img src={logo} className="logo" alt="logo" /> //className='logo' -> css에서 사용
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
...
9. 2 ) Sass 사용하기
Sass( Syntactically Awesome Style sheets )는 css의 전처리기로 복잡한 작업을 쉽게 할 수 있도록 해 주고, 스타일 코드의 재활용성을 높여 줄 뿐만 아니라 코드의 가독성을 높여서 유지 보수를 더욱 쉽게 해준다.
Sass에서는 두가지 확장자 .scss 와 .sass를 지원하는데 .scss 문법이 더 자주 사용된다.
Sass를 CSS로 변환해주는 node-sass라는 라이브러리를 설치해준다 ( $ yarn add node-sass )
SassComponent. scss
/*변수 사용하기*/
$red: #fa5252;
$orange: #fd7e14;
$yellow: #fcc419;
$green: #40c057;
$blue: #339af0;
$indigo: #5c7cfa;
$violet: #7950f2;
/*믹스인 만들기 (재사용되는 스타일 블록을 함수처럼 사용할 수 있음)*/
@mixin square($size) {
$caculated: 32px * $size;
width: $caculated;
height: $caculated;
}
.SassComponent {
display: flex;
.box {/*일반 css에서는 .SassComponent .box와 같다.*/
background: red;
cursor: pointer;
transition: all 0.3s ease-in;
&.red {/*.red 클래스가 .box와 함께 사용되었을 때*/
background: $red;
@include square(1);
}
&.orange {
background: $orange;
@include square(2);
}
&.yellow {
background: $yellow;
@include square(3);
}
&.green {
background: $green;
@include square(4);
}
&.blue {
background: $blue;
@include square(5);
}
&.indigo {
background: $indigo;
@include square(6);
}
&.violet {
background: $violet;
@include square(7);
}
&:hover {/*.box에 마우스를 올렸을 때*/
background: black;
}
}
}
위의 스타일시트를 사용하는 SassComponent. js 컴포넌트 파일
import React from "react";
import "./SassComponent.scss";
const SassComponent = () => {
return (
<div className="SassComponent">
<div className="box red" />
<div className="box orange" />
<div className="box yellow" />
<div className="box green" />
<div className="box blue" />
<div className="box indigo" />
<div className="box violet" />
</div>
);
};
export default SassComponent;
App 컴포넌트 파일에서 보여주기
import React from "react";
import SassComponent from "./SassComponent"; //가져오기
function App() {
return (
<div>
<SassComponent />
</div>
);
}
export default App;
9. 2. 1 ) utils 함수 분리하기
여러파일에서 사용될 수 있는 Sass변수 및 믹스인은 다른 파일로 따로 분리하여 작성한 뒤 필요한 곳에 불러와서 사용할 수 있다.
- src디렉터리 → styles디렉터리 생성 → utils.scss파일 생성
- utils.scss 에 SassComponent. scss에서 작성했던 Sass변수, 믹스인민 잘라내서 이동.
- SassComponent. scss에서 utils. scss 파일을 불러와서 사용 ( @import './Styles/utils'; )
9. 2. 2 ) sass-loader 설정 커스터마이징 하기
예를 들어 SassComponent. scss 에서 utils. scss를 불러올 때 @import './Styles/utils'; 형태로 불러왔는데 디렉터리를 많이 만들어 구조가 깊어졌다면 세부 설정을 커스터마이징 하여 해결할 수 있다.
-
yarn eject 명령어를 통해 세부 설정을 밖으로 꺼내준다.
-
위의 명령어로 인해 생성된 config 디렉터리 안의 webpack. config. js 파일에서 'sassRegex' 키워드를 찾아 커스터마이징 된 sass-loader를 넣어준다.
-
이제 utils. scss 파일을 불러올 때 상대경로를 입력할 필요 없이 styles 디렉터리 기준 절대 경로를 사용하여 불러올 수 있다. ( @import 'utils. scss'; )
- 이것도 귀찮으면 sass-loader의 data옵션을 설정하면 Sass파일을 불러올 때마다 코드의 맨 윗부분에 특정 코드를 포함시켜 준다.
9. 2. 3 ) node_modules에서 라이브러리 불러오기
Sass의 장점 중 하나는 라이브러리를 쉽게 불러와서 사용할 수 있다는 점이다.
상대 경로를 사용하여 불러올 수도 있고, 구조가 깊은 경우에는 ~를 사용할 수도 있다. 물결문자를 사용하면 자동으로 node_modules에서 라이브러리 디렉터리를 탐지하여 스타일을 불러올 수 있다. ( @import '~library/styles'; )
9. 3 ) CSS Module
CSS Module은 CSS를 불러와서 사용할 때 클래스 이름을 고유한 [ 파일 이름 ]_[ 클래스 이름 ]_[ 해시값 ] 형태로 자동으로 만들어서 컴포넌트 스타일 클래스 이름이 중첩되는 현상을 방지해 주는 기술이다.
.module. css 확장자로 파일을 저장하면 자동으로 CSS Module이 적용된다.
CSSModule.module.css
/*자동으로 고유해지므로 흔히 사용하는 단어를 클래스 이름으로 마음대로 사용 가능하다*/
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
}
/*글로벌 css를 작성할 때*/
:global .something {
font-weight: 800;
color: aqua;
}
해당 클래스는 내가 만든 스타일을 직접 불러온 컴포넌트 내부에서만 작동하고, 특정 클래스가 웹 페이지 전역적으로 사용되는 경우에는 :global을 앞에 입력해준다.
CSSModule. js ( 위의 CSSModule을 사용하는 리액트 컴포넌트 )
import React from "react";
import styles from "./CSSModule.module.css";
const CSSModule = () => {
return (
<div className={styles.wrapper}>
// 스타일 클래스를 적용하고 싶은 요소에 {styles.[클래스이름]} 형태로 전달
안녕하세요, 저는 <span className="something">CSS Module</span>
// 글로벌은 그냥 넣어줌
</div>
);
};
export default CSSModule;
App. js 에서 CSSModule 컴포넌트를 렌더링
import React from "react";
import CSSModule from "./CSSModule";
function App() {
return (
<div>
<CSSModule />
</div>
);
}
export default App;
( 실행화면 )

CSS Module을 사용한 클래스 이름을 두개 이상 적용하고 싶을 땐, CSSModule. js에서 <div className={ `${ styles.wrapper } ${ styles.inverted }` }> 형태로 작성한다.
// 위의 코드는 템플릿 리터럴 문법을 사용하여 문자열을 합쳐준 것이다. ( const message = ` 이름은 ${ name }입니다 `; )
이외에도 className={ [ styles.wrapper, styles.inverted ] .join(' ') }으로 작성하는 방법이 있다.
9. 3. 1 ) classnames
classnames는 CSS클래스를 조건부로 설정할 때 매우 유용한 라이브러리이다.
$ yarn add classnames 로 해당 라이브러리를 설치한다.
import classNames from 'classnames';
classNames('one','two'); // = 'one two'
const myClass = 'hello';
classNames('one', myClass, { myCondition: true }); // = 'one hello myCondition'
//highlighted가 참이어야 highlighted 클래스가 적용된다, theme으로 전달받는 문자열은 내용 그대로 클래스에 적용
const MyComponent = ({highlighted, theme}) => {
<div className= {classNames('MyComponent', {highlighted}, theme)}> Hello </div>
};
여러가지 종류의 파라미터를 조합해 CSS클래스를 설정할 수 있기 때문에 컴포넌트에서 조건부로 클래스를 설정할 때 매우 편리하다.
또한 CSS Module과 함께 사용이 훨씬 쉬워진다. classnames에 내장되어 있는 bind함수를 사용하면 styles.[ 클래스 이름 ] 형태를 쓸 필요가 없어진다.
const cx = classNames. bind( styles ); // 미리 styles에서 클래스를 받아오도록 설정
<div className={ cx( 'wrapper', 'inverted' )}>
9. 3. 2 ) Sass와 함께 사용하기
Sass를 사용할 때도 파일 이름 뒤에 module.scss 확장자를 사용해 주면 CSS Module로 사용할 수 있다.
CSSModule.module.css에서 &.inverted { ... }, :global { ... } 로 작성해준다.
/*자동으로 고유해지므로 흔히 사용하는 단어를 클래스 이름으로 마음대로 사용 가능하다*/
.wrapper {
...
}
&.inverted { /*inverted가 wrapper와 함께 사용되었을 때만 적용*/
...
}
/*글로벌 css를 작성할 때*/
:global{
...
}
9. 3. 3 ) CSS Module이 아닌 파일에서 CSS Module 사용하기
CSS Module이 아닌 일반 .css/ .scss파일에서도 :local을 사용하여 CSS Module을 사용할 수 있다.
( :local .wrapper { /*스타일*/ } 또는 :local { .wrapper{ /*스타일*/ } } )
9. 4 ) styled-components
자바스크립트 파일 안에 스타일을 선언하는 'CSS-in-JS' 중에서 가장 많이 쓰이는 styled-components 라이브러리
$ yarn add styled-components 로 해당 라이브러리를 설치한다.
StyledComponent. js
import React from "react";
import styled, { css } from "./styled-components";
const Box = styled.div`
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;
&:hover {
background: rgba(255, 255, 255, 0.9);
}
${(props) =>
props.inverted &&
css`
background: none;
border: 2px solid white;
color: white;
&:hover {
background: white;
color: black;
}
`};
& + button {
margin-left: 1rem;
}
`;
const StyledComponent = () => {
<Box color="black">
<Button>안녕하세요</Button>
<Button inverted={true}>테두리안</Button>
</Box>;
};
export default StyledComponent;
styled- components의 가장 큰 장점은 'props값으로 전달해 주는 값을 쉽게 스타일에 적용' 할 수 있다는 것이다.
9. 4. 1 ) Tagged 템플릿
스타일을 작성할 때 `를 사용하여 만든 문자열에 스타일 정보를 넣어준다.
일반 템플릿 리터럴과 다르게 템플릿 안에 자바스크립트 객체나 함수를 전달할 때 온전히 추출할 수 있다.
9. 4. 2 ) 스타일링된 엘리먼트 만들기
styled.태그명 뒤에 Tagged 템플릿 리터럴 문법을 통해 스타일을 넣어 주면 해당 스타일이 적용된 태그로 이루어진 리액트 컴포넌트가 생성된다. 그 후에 <Box>hello</Box>형태로 사용할 수 있다.
하지만 사용해야 할 태그명이 유동적이거나 특정 컴포넌트 자체에 스타일링 해주고 싶다면 아래와 같이 작성한다.
const MyInput = styled( 'input' )` ... ` //태그의 타입을 styled 함수의 인자로 전달
const StyledLink = styled( Link )` ... ` //아예 컴포넌트 형식의 값을 넣어줌
9. 4. 3 ) 스타일에서 props 조회하기
styled-components를 사용하면 스타일 쪽에서 컴포넌트에게 전달된 props 값을 참조할 수 있다.
const Box = styled. div `
background: ${ props => props. color || 'blue' } ;
... //props값을 조회해서 props.color의 값을 사용, color값이 주어지지 않았을때는 blue사용
` ;
이 코드는 <Box color='balck'>...</Box>와 같이 사용된다.
9. 4. 4 ) props에 따른 조건부 스타일링
일반 CSS클래스에서는 className을 사용하여 조건부 스타일링을 해 왔는데, styled-components에서는 조건부 스타일링을 간단하게 props으로 처리할 수 있다.
StyledComponents. js - Button의 스타일에서 ${ props => props. inverted (inverted ={ true }이면 적용) && css` background: none; ...` (css를 불러와서 Tagged 템플릿으로 감싸주기) };
9. 4. 5 ) 반응형 디자인
브라우저의 가로 크기에 따라 다른 스타일을 적용하기 위해서는 일반 CSS와 같이 'media쿼리' 를 사용한다.
StyledComponents. js - Box //기본적으로는 가로 크기 1024px에 가운데 정렬을 하고, 가로 크기가 작아짐에 따라 크기를 줄이고 768px 미만이 되면 꽉 채운다.
const Box = styled.div`
background: ${(props) => props.color || "blue"};
padding: 1rem;
display: flex;
width: 1024px;
margin: 0 auto;
@media (max-width: 1024px) {
width: 768px;
}
@media (max-width: 768px) {
width: 100%;
}
`;
이런 작업을 함수화할 수도 있다.
const sizes = {
desktop: 1024,
tablet: 768
};
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: 1024px;`} 로 작성한다.
실제로 사용할 때는 아예 다른 파일로 모듈화한 뒤 불러와 사용하는 방식이 편하다.
'리액트 > 리액트를 다루는 기술' 카테고리의 다른 글
11장. 컴포넌트 성능 최적화 (0) | 2021.01.23 |
---|---|
10장. 일정관리 웹 애플리케이션 만들기 (0) | 2021.01.21 |
리액트 8강. Hooks (0) | 2021.01.14 |
리액트 7장. 컴포넌트의 라이프사이클 메서드 (0) | 2021.01.07 |
리액트 6장. 컴포넌트 반복 (0) | 2021.01.06 |