[REACT] React - .css .scss 사용
<리액터를 다루는 기술 10장을 활용한 예제>
- 책에 나와 있는 sass의 환경설정은 지금 버전이 바뀌어 지원을 하지 않고 있기 때문에 아래와 같이 환경설정해서 사용하면 된다.
1. .css .scss 사용을 위한 기본 설정
.css .scss 등 스타일링에 필요한 라이브러리
npm install node-sass --save
npm install open-color --save
npm install sass-loader --save
npm install classnames --save
index.css가 실질적으로 백그라운드에 영향을 준다.
.scss를 사용 하기 위해서는 index.js 파일에서 import를 변경시켜 주어야 한다.
.scss로 변경하더라도 .css 확장자명을 설정 변경없이 사용이 가능하다.
index.css의 확장자를 index.scss 로 변경해 주어야 한다.
변경을 하고 index.scss의 내용도 scss의 문법으로 변경해 주어야 한다.
* 컴파일 하다가 Error 발생시 모듈을 지웠다가 다시 깔아보기.
* npm install node-sass 설치시 에러가 발생하면 Visual C++ 관련 빌드툴이 깔려있지 않은 경우이다. vs를 설치하고 npm install windows-build-tools를 실행하면 된다.
Ex01. 컴포넌트의 백그라운드 색깔 지정
// App.js
import React, { Component } from 'react';
// Cpp에서 classname을 통해 접근을 하기 위해서 import
import classNames from 'classnames/bind';
import b from './B.scss'
class App extends Component {
render() {
return (
<div>
<Bpp/>
<Cpp/>
</div>
);
}
}
const Bpp = () => {
return (
<div className={'RedBox'}>
콩콩이
</div>
);
};
const Cpp = () => {
const bx = classNames.bind(b);
return (
<div className={bx('GreenBox')}>
댕댕이
</div>
);
};
export default App;
Ex02. PageTamplate 구현
// App.js
import React, { Component } from 'react';
// Cpp에서 classname을 통해 접근을 하기 위해서 import
import classNames from 'classnames/bind';
import pageTamlate from './PageTamplate.scss'
class App extends Component {
render() {
return (
<div>
<Fpp/>
</div>
);
}
}
// PageTamplate(Fpp)
class Fpp extends Component {
render() {
const cx = classNames.bind(pageTamlate);;
return (
<div className={cx("page-template")}>
<h1>일정관리</h1>
<div className={cx("content")}>
안녕하세요.
</div>
</div>
);
}
}
export default App;
// PageTamplate.scss
.page-template {
margin-top: 5rem;
margin-left: auto;
margin-right: auto;
width: 500px;
background: white;
// 그림자를 띄워줍니다.
box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
padding-top: 2rem;
// 브라우저의 크기가 768px 미만으로 됐을 땐,
@media(max-width: 768px) {
margin-top: 1rem;
width: calc(100% - 2rem); // 양 옆에 1rem의 여백을 남기고 꽉 채워줍니다.
}
h1 {
text-align: center;
font-size: 4rem;
font-weight: 300;
margin: 0;
}
.content {
margin-top: 2rem;
}
}
Ex03. TodoInput 구현
// App.js
import React, { Component } from 'react';
// Cpp에서 classname을 통해 접근을 하기 위해서 import
import classNames from 'classnames/bind';
import todoinput from './TodoInput.scss'
class App extends Component {
render() {
return (
<div>
<Gpp/>
</div>
);
}
}
// TodoInput(Gpp)
const Gpp = () => {
const cx = classNames.bind(todoinput)
return (
<div className={cx('todo-input')}>
<input value='여기에 입력' onChange={() => { }}></input>
<div className={cx('add-button')}>추가</div>
</div>
);
};
export default App;
// TodoInput.scss
@import '~open-color/open-color';
.todo-input {
border-top: 1px solid $oc-gray-2;
border-bottom: 1px solid $oc-gray-2;
// 손쉬운 레이아웃 설정을 위하여 flex를 사용합니다.
display: flex;
padding: 1rem;
input {
// 인풋의 기본 스타일을 지우고 새 스타일을 정의합니다.
flex: 1; // 부모 엘리먼트에서 add-button을 제외한 나머지 공간을 차지합니다.
font-size: 1.1rem;
outline: none;
border: none;
background: transparent;
border-bottom: 1px solid $oc-gray-4;
&:focus {
border-bottom: 1px solid $oc-cyan-6;
}
}
.add-button {
width: 5rem;
height: 2rem;
margin-left: 1rem;
border: 1px solid $oc-green-7;
color: $oc-green-7;
font-weight: 500;
font-size: 1.1rem;
display: flex;
// 내용을 가운데에 정렬시킵니다.
align-items: center;
justify-content: center;
cursor: pointer;
&:hover {
background: $oc-green-7;
color: white;
}
&:active {
background: $oc-green-8;
}
}
}
Ex04. PageTamplate에 TodoInput 추가하는 3가지 방법
import React, { Component } from 'react';
// Cpp에서 classname을 통해 접근을 하기 위해서 import
import classNames from 'classnames/bind';
import todoinput from './TodoInput.scss'
class App extends Component {
render() {
return (
<div>
{/* pageTamplate안에 todoinput 포함시키기 */}
{/* 첫번째 방법, Hpp 컴포넌트 자체에 Gpp 포함하기 */}
<Hpp/>
{/* Ipp에서 Gpp 컴포넌트를 children으로 받기 */}
<Ipp>
<Gpp/>
</Ipp>
{/* Jpp에서 Gpp 컴포넌트를 props로 받기 */}
<Jpp>
<Gpp/>
</Jpp>
</div>
);
}
}
// TodoInput(Gpp)
const Gpp = () => {
const cx = classNames.bind(todoinput)
return (
<div className={cx('todo-input')}>
<input value='여기에 입력' onChange={() => { }}></input>
<div className={cx('add-button')}>추가</div>
</div>
);
};
// PageTamplate(Hpp)에 직접 TodoInput(Gpp) 추가
class Hpp extends Component {
render() {
const cx = classNames.bind(todoinput);;
return (
<div className={cx("page-template")}>
<h1>일정관리</h1>
<div className={cx("content")}>
<Gpp />
</div>
</div>
);
}
}
// PageTamplate(Ipp)에서 children 사용하여 하위 태그 받음
const Ipp = ({ children }) => {
const cx = classNames.bind(todoinput)
return (
<div className={cx('page-template')}>
<h1>일정관리</h1>
<div className={cx('content')}>
{children}
</div>
</div>
);
};
// PageTamplate(Jpp)에서 전달받은 props 사용
class Jpp extends Component {
render() {
const cx = classNames.bind(todoinput)
return (
<div className={cx('page-template')}>
<h1>일정관리</h1>
<div className={cx('content')}>
{/* props로 받는다. */}
{this.props.children}
</div>
</div>
);
}
}
export default App;
// TodoInput.scss
@import '~open-color/open-color';
.todo-input {
border-top: 1px solid $oc-gray-2;
border-bottom: 1px solid $oc-gray-2;
// 손쉬운 레이아웃 설정을 위하여 flex를 사용합니다.
display: flex;
padding: 1rem;
input {
// 인풋의 기본 스타일을 지우고 새 스타일을 정의합니다.
flex: 1; // 부모 엘리먼트에서 add-button을 제외한 나머지 공간을 차지합니다.
font-size: 1.1rem;
outline: none;
border: none;
background: transparent;
border-bottom: 1px solid $oc-gray-4;
&:focus {
border-bottom: 1px solid $oc-cyan-6;
}
}
.add-button {
width: 5rem;
height: 2rem;
margin-left: 1rem;
border: 1px solid $oc-green-7;
color: $oc-green-7;
font-weight: 500;
font-size: 1.1rem;
display: flex;
// 내용을 가운데에 정렬시킵니다.
align-items: center;
justify-content: center;
cursor: pointer;
&:hover {
background: $oc-green-7;
color: white;
}
&:active {
background: $oc-green-8;
}
}
}
Ex05. PageTamplate에 TodoInput 추가에 이어 TodoItem도 추가
// App.js
import React, { Component } from 'react';
// Cpp에서 classname을 통해 접근을 하기 위해서 import
import classNames from 'classnames/bind';
import todoinput from './TodoInput.scss'
import todoitem from './TodoItem.scss'
class App extends Component {
render() {
return (
<div>
{/* Ipp에서 Gpp 컴포넌트를 children으로 받기 */}
<Ipp>
<Gpp/>
<Kpp/>
</Ipp>
</div>
);
}
}
// TodoInput(Gpp)
const Gpp = () => {
const cx = classNames.bind(todoinput)
return (
<div className={cx('todo-input')}>
<input value='여기에 입력' onChange={() => { }}></input>
<div className={cx('add-button')}>추가</div>
</div>
);
};
// PageTamplate(Ipp)에 하위태그를 children으로 받음
const Ipp = ({ children }) => {
const cx = classNames.bind(todoinput)
return (
<div className={cx('page-template')}>
<h1>일정관리</h1>
<div className={cx('content')}>
{children}
</div>
</div>
);
};
// TodoItem(Kpp)
class Kpp extends Component {
render() {
const ex = classNames.bind(todoitem)
return (
<div className={ex('todo-item')}>
<input className={ex('tick')} type="checkbox" checked={true} readOnly />
{/* <div className={ex('text')}>{this.props.children}</div> */}
<div className={ex('text')}>일정관리하자!!!!!!!!!</div>
<div className={ex('delete')} onClick={(e) => {
e.stopPropagation();
}
}>[지우기]</div>
</div>
);
}
}
export default App;
// TodoItem.scss
@import '~open-color/open-color';
.todo-item {
padding: 1rem;
display: flex;
align-items: center;
cursor: pointer;
.tick {
margin-right: 1rem;
}
.text {
flex: 1;
word-break: break-all;
&.done {
text-decoration: line-through;
}
}
.delete {
margin-left: 1rem;
color: $oc-red-7;
font-size: 0.8rem;
&:hover {
color: $oc-red-5;
text-decoration: underline;
}
}
&:nth-child(odd) {
// 홀수 번째 엘리먼트에는 회색 배경
background: $oc-gray-0;
}
&:hover {
background: $oc-gray-1;
}
}
.todo-item + .todo-item {
// 컴포넌트 사이 사이에 위쪽 테두리를 설정합니다.
border-top: 1px solid $oc-gray-1;
}
Ex06. .css 사용 - 버튼 디자인 하기
- css의 경우 w3school.com 등 사이트에서 끌어와서 사용하는 법 정도만 익히면 된다.
// App.js
import React, { Component } from 'react';
import './button.css'
class App extends Component {
render() {
return (
<div>
{/* w3schools.com의 css 버튼 끌어오기 */}
<button class="button">Green</button>
<button class="button button2">Blue</button>
<button class="button button3">Red</button>
<button class="button button4">Gray</button>
<button class="button button5">Black</button>
</div>
);
}
}
export default App;
// button.css
.button {
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
}
.button2 {background-color: #008CBA;} /* Blue */
.button3 {background-color: #f44336;} /* Red */
.button4 {background-color: #e7e7e7; color: black;} /* Gray */
.button5 {background-color: #555555;} /* Black */
2019.08.13(화)
.css .scss의 사용