React에서 Scss를 사용해보자
html요소의 스타일을 변경하는방법은 여러가지가 있지만, 인라인이나 파일안에 직접 스타일요소를 적는 방법보단 css파일을 하나 생성하여 연결한 후 사용하는 방법을 사용하는게 일반적이다
React에서도 마찬가지이지만 방법이 살짝 다르다
React는 js파일이기 때문에 html과 다르게 import
로 해당 css파일을 연결한다
import 'css파일 path'
html에서 css파일의 셀렉터에 접근하는 방법은 다음과 같았다
class='클래스 이름'
하지만 React를 사용할 땐 js에 class라는 예약어가 이미 있기 때문에 className으로 접근해야한다 (마찬가지로 js임으로 class-name와 같은 이름은 쓰지 않는다)
그럼 위의 내용을 토대로 실제 프로젝트에 적용해보자
// App.js
import React from 'react';
import Button from './Button';
import './App.scss';
class App extends React.Component {
render() {
return (
<main>
<Button />
</main>
);
}
}
export default App;
// button.js
import React from 'react';
import './Button.scss';
class Button extends React.Component {
render() {
return (
<button className="button">
버튼
</button>
);
}
}
export default Button;
// App.scss
main {
text-align: center;
}
// button.scss
.button {
width: 100px;
height: 30px;
color: white;
background-color: tomato;
}
App, Button 컴포넌트와 scss파일을 생성하고
<button className="button">버튼</button>
와 같이 className을 통해 스타일링을 해주었다
위의 버튼을 스위치로 사용하고 싶고 그에 따라 on/off 상태에서 다른 배경색을 부여하고 싶으면 조건부 스타일링을 해야한다
하지만 위의 예처럼 고정된 값을 주면 조건부 스타일링을 할 수 없다
따라서 className에 변수를 할당해야한다
// onClick 이벤트를 통해 className의 배경색을 변경해보자
// button.js
import React from 'react';
import './Button.scss';
class Button extends React.Component {
constructor() {
super();
this.state = {
btnState: 'on',
};
}
handleBtn = () => {
this.state.btnState === 'on'
? this.setState({
btnState: 'off',
})
: this.setState({
btnState: 'on',
});
};
render() {
console.log(this.state.btnState);
return (
<button className={`Button ${this.state.btnState}`} onClick={this.handleBtn}>
버튼
</button>
);
}
}
export default Button;
// button.scss
.Button {
width: 100px;
height: 30px;
color: white;
&.on {
background-color: tomato;
}
&.off {
background-color: teal;
}
}
위처럼 버튼을 눌렀을 시 배경색이 변경되는 것을 볼 수 있다
scss파일의 &
는 부모를 의미한다
따라서 .Button.on .Button.off
를 말하며 만약 &.을 적지 않았을 경우 제대로 적용이 되지 않는다
위와 같이 템플릿 리터럴을 이용해도 되지만 classnames라는 라이브러리를 사용하면 좀 더 편하게 조건부 스타일링을 할 수 있다
npm install classnames
<button className={classNames('Button', this.state.btnState)} onClick={this.handleBtn}>
classNames('Button', this.state.btnState)
와 같이 사용 할 수 있다
꼭 써야할까요? 🤔
템플릿 리터럴의 경우 해당 속성이 셀렉터로 변환될 때 모든 문자열을 체크하기 때문에 띄어쓰기까지 일치하도록 해야한다그렇기에 필자는 해당 라이브러리를 활용하는 편이 조금 더 좋아보이지만 항상 그렇듯 프로젝트, 팀원들의 사용여부에 따라 결정하는 것이 맞다고 생각한다
번외) SCSS 변수 활용하기
css에서도 변수를 사용 할 수 있지만 scss에서는에서는 좀 더 쉽게 변수를 선언해 사용 할 수 있다$onColor: tomato; $offColor: teal; .Button { width: 100px; height: 30px; color: white; &.on { background-color: $onColor; } &.off { background-color: $offColor; } }
$변수이름 : 값;
으로 변수를 선언하고$변수이름
으로 사용 할 수 있다현재는 한 가지 경우에만 사용되는 컬러를 변수로 만들었기에 쓸모가 없어보이지만 해당 컬러가 프로젝트에서 자주 사용되는 컬러일경우
basicColor: #2d9a6d;
와 같이 선언한 후 여러 곳에서 사용 하는 편이 좋다
(공통 css 폴더에 놓고 사용하기도 한다)왜냐하면 여러곳에서 사용되는데 변수로 만들지 않고 사용한다면
#2d9a6d
값을 외워놓고 작성할 때마다 써야 할 것이기 때문이다Mixin
만약 중복되는 코드가 있고, 조건에 따라 다른 스타일을 scss에서 구현하고 싶다면 Mixin 을 사용하면 된다@mixin 이름(인자) { 내용 } .Button { @include mixin이름(전달할 값); } 위와 같이 사용하면 중복코드를 제거하고 전달할 값에 따라 다른 스타일링이 가능하다 심지어 조건문도 작성이 가능하기 때문에 마치 프로그래밍 언어처럼 사용할 수 있다 @if 조건1 { 내용 } @else if 조건2 { 내용 } @else { 내용 }