이번에 리엑트 토이프로젝트를 하면서, CSS에 대해 이것저것 알아보던 중
Scss에 대해 잘 정리된 블로그가 있어 잊어먹지 않게 내 블로그에도 정리해본다 ~
Scss
Sass (Syntactically Awesome Style Sheets: 문법적으로 짱 멋진 스타일시트) 는 CSS pre-processor 로서, 복잡한 작업을 쉽게 할 수 있게 해주고, 코드의 재활용성을 높여줄 뿐 만 아니라, 코드의 가독성을 높여주어 유지보수를 쉽게한다
보통 scss 문법이 더 많이 사용되므로, 나는.scss 확장자로 스타일을 작성하겠다
node-sass는 지원이 끝났으므로, Dart-sass를 설치하도록 하자 !
npm install -g sass
Button 컴포넌트 만들기
Button이라는 컴포넌트를 만들고, Scss를 이용해서 스타일링을 하자 !
src > components 디렉터리 생성 후 그 안에 Button.js를 생성 !
Button.js
import React from 'react';
import './Button.scss';
function Button({ children }) {
return <button className="Button">{children}</button>;
}
export default Button;
그 다음 같은 디렉토리에 Button.scss도 작성!
Button.scss
$blue: #228be6; // 주석 선언
.Button {
display: inline-flex;
color: white;
font-weight: bold;
outline: none;
border-radius: 4px;
border: none;
cursor: pointer;
height: 2.25rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1rem;
background: $blue; // 주석 사용
&:hover {
background: lighten($blue, 10%); // 색상 10% 밝게
}
&:active {
background: darken($blue, 10%); // 색상 10% 어둡게
}
}
1. $blue: #228be6; 와같이 변수도 사용할 수 있다
2. lighten() 또는 darken() 과 같이 색상을 더 밝게하거나 어둡게 해주는 함수도 사용 할 수 있다.
이제 App.js 나 사용하고자 하는 컴포넌트에서 사용하자 !
App.js
import React from 'react';
import './App.scss';
import Button from './components/Button';
function App() {
return (
<div className="App">
<div className="buttons">
<Button>BUTTON</Button>
</div>
</div>
);
}
export default App;
버튼이 아주 이쁘게 잘 만들어졌다.
버튼 사이즈 조정하기
우선 크기에 large, medium, small을 설정할 수 있도록 구현을 하자
Button.js에서 다음과 같이 defaultProps를 통하여 size의 기본값을 medium으로 설정하고 이 값은 button의 className에 넣자 ~
※ className 패키지를 사용하면 이쁘게 할 수 있으나 난 건너뜀 ~
classNames 샘플
classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
classNames(['foo', 'bar']); // => 'foo bar'
// 동시에 여러개의 타입으로 받아올 수 도 있습니다.
classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux'
// false, null, 0, undefined 는 무시됩니다.
classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
Button.js
import React from 'react';
import './Button.scss';
function Button({ children, size }) {
return <button className={`Button ${size}`}>{children}</button>;
}
Button.defaultProps = {
size: 'medium'
};
export default Button;
Button.scss
$blue: #228be6;
.Button {
display: inline-flex;
color: white;
font-weight: bold;
outline: none;
border-radius: 4px;
border: none;
cursor: pointer;
// 사이즈 관리
&.large {
height: 3rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1.25rem;
}
&.medium {
height: 2.25rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1rem;
}
&.small {
height: 1.75rem;
font-size: 0.875rem;
padding-left: 1rem;
padding-right: 1rem;
}
background: $blue;
&:hover {
background: lighten($blue, 10%);
}
&:active {
background: darken($blue, 10%);
}
& + & {
margin-left: 1rem;
}
}
- 위 코드에서 .Button&.large가 의미하는 것은 .Button.large와 같다.
- & + & zhemsms .Button + .Button 을의미한다. 만약 버튼이 붙어있으면, 여백을 설정하기 위함이다.
App.js에 버튼들을 2개 더 추가한다.
App.js
import React from 'react';
import './App.scss';
import Button from './components/Button';
function App() {
return (
<div className="App">
<div className="buttons">
<Button size="large">BUTTON</Button>
<Button>BUTTON</Button>
<Button size="small">BUTTON</Button>
</div>
</div>
);
}
export default App;
버튼이 이쁘게 잘 만들어졌다. 이번에는 색상별로 설정을 해보도록 하자.
버튼 색상 설정하기
이번에는 버튼에 파란색 외에 다른 색상을 설정하는 작업에 대해 알아보자, 버튼의 색상에는 blue, gray, pink를 설정할 수 있도록 구현할 것이다.,
※ 개발 시 색상이 고민이 들때 https://yeun.github.io/open-color/
Open Color
Color scheme for UI design
yeun.github.io
링크를 참고하도록 하자.
Button.js
import React from 'react';
import classNames from 'classnames';
import './Button.scss';
function Button({ children, size, color }) {
return (
<button className={classNames('Button', size, color)}>{children}</button>
);
}
Button.defaultProps = {
size: 'medium',
color: 'blue'
};
export default Button;
Button.scss
$blue: #228be6;
$gray: #495057;
$pink: #f06595;
@mixin button-color($color) {
background: $color;
&:hover {
background: lighten($color, 10%);
}
&:active {
background: darken($color, 10%);
}
}
.Button {
display: inline-flex;
color: white;
font-weight: bold;
outline: none;
border-radius: 4px;
border: none;
cursor: pointer;
// 사이즈 관리
&.large {
height: 3rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1.25rem;
}
&.medium {
height: 2.25rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1rem;
}
&.small {
height: 1.75rem;
font-size: 0.875rem;
padding-left: 1rem;
padding-right: 1rem;
}
// 색상 관리
&.blue {
@include button-color($blue);
}
&.gray {
@include button-color($gray);
}
&.pink {
@include button-color($pink);
}
& + & {
margin-left: 1rem;
}
}
코드의 상단에서 색상 변수를 선언해주었고, 하단에서 className에 따라 다른 색상이 적용되도록 하였다.
※ Color는 Sass에서 제공해주는 mixin이라는 기능을 이용하여 간결하게 하였다 소스를 참고해보자
App.js
import React from 'react';
import './App.scss';
import Button from './components/Button';
function App() {
return (
<div className="App">
<div className="buttons">
<Button size="large">BUTTON</Button>
<Button>BUTTON</Button>
<Button size="small">BUTTON</Button>
</div>
<div className="buttons">
<Button size="large" color="gray">
BUTTON
</Button>
<Button color="gray">BUTTON</Button>
<Button size="small" color="gray">
BUTTON
</Button>
</div>
<div className="buttons">
<Button size="large" color="pink">
BUTTON
</Button>
<Button color="pink">BUTTON</Button>
<Button size="small" color="pink">
BUTTON
</Button>
</div>
</div>
);
}
export default App;
버튼 이미지가 잘 나왔다 .
large 이미지가 다닥 다닥 붙어 있어 보기싫다.
app.scss를 수정해주도록 하자 !
App.scss
.App{
.buttons + .buttons {
margin-top : 1rem;
}
}
이쁘게 잘 떨어져 있다 ~
outline 옵션 만들기
이번에는 outline 이라는 옵션을 주면 버튼에서 테두리만 보이는 설정을 해보도록 하자
- outline은 true, false여부로 설정할거라 classnames 패키지를 설치하였다 ! 참고하자
Button.js
import React from 'react'
import './Button.scss'
import classNames from 'classnames'
export function Button({ text, size, color, outline }) {
return (
<button className={classNames('Button', size, color, { outline })}>
{text}
</button>
)
}
Button.defaultProps = {
size: 'medium',
color: 'blue',
}
export default Button
Button.scss
$blue: #228be6;
$gray: #495057;
$pink: #f06595;
@mixin button-color($color) {
background: $color;
&:hover {
background: lighten($color, 10%);
}
&:active {
background: darken($color, 10%);
}
&.outline {
color: $color;
background: none;
border: 1px solid $color;
&:hover {
background: $color;
color: white;
}
}
}
.Button {
display: inline-flex;
color: white;
font-weight: bold;
outline: none;
border-radius: 4px;
border: none;
cursor: pointer;
height: 2rem;
padding-left: 1rem;
padding-right: 1rem;
padding-top: 0.4rem;
font-size: 1rem;
//사이즈 관리
&.large {
height: 2.4rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1.25rem;
}
&.medium {
height: 2.25rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1.25rem;
}
&.small {
height: 1.75rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 0.875rem;
}
&.blue {
@include button-color($blue);
}
&.gray {
@include button-color($gray);
}
&.pink {
@include button-color($pink);
}
& + & {
margin-left: 1rem;
}
}
App.js
import React from 'react'
import Button from '../components/Button'
import SampleCss from '../components/Sample.scss'
export function Sample() {
return (
<div className="Sample">
<div className="buttons">
<Button color="blue" size="small" text="유닛등록"></Button>
<Button text="유닛등록"></Button>
<Button size="large" text="유닛등록"></Button>
</div>
<div className="buttons">
<Button color="gray" size="small" text="유닛등록"></Button>
<Button color="gray" text="유닛등록"></Button>
<Button color="gray" size="large" text="유닛등록"></Button>
</div>
<div className="buttons">
<Button color="pink" size="small" text="유닛등록"></Button>
<Button color="pink" text="유닛등록"></Button>
<Button color="pink" size="large" text="유닛등록"></Button>
</div>
<div className="buttons">
<Button color="pink" size="small" text="유닛등록" outline></Button>
<Button color="blue" text="유닛등록" outline></Button>
<Button color="gray" size="large" text="유닛등록" outline></Button>
</div>
</div>
)
}
export default Sample
전체너비 버튼 생성
이번에는 fullWidth 옵션이 있으면 버튼을 전체 너비를 차지하도록 설정을 해보도록 하자
outline과 비슷하다 !!
Button.js
import React from 'react'
import './Button.scss'
import classNames from 'classnames'
export function Button({ text, size, color, outline, fullWidth }) {
return (
<button
className={classNames('Button', size, color, { outline, fullWidth })}
>
{text}
</button>
)
}
Button.defaultProps = {
size: 'medium',
color: 'blue',
}
export default Button
Button.scss
$blue: #228be6;
$gray: #495057;
$pink: #f06595;
@mixin button-color($color) {
background: $color;
&:hover {
background: lighten($color, 10%);
}
&:active {
background: darken($color, 10%);
}
&.outline {
color: $color;
background: none;
border: 1px solid $color;
&:hover {
background: $color;
color: white;
}
}
}
.Button {
display: inline-flex;
color: white;
font-weight: bold;
outline: none;
border-radius: 4px;
border: none;
cursor: pointer;
height: 2rem;
padding-left: 1rem;
padding-right: 1rem;
padding-top: 0.4rem;
font-size: 1rem;
//사이즈 관리
&.large {
height: 2.4rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1.25rem;
}
&.medium {
height: 2.25rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1.25rem;
}
&.small {
height: 1.75rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 0.875rem;
}
&.blue {
@include button-color($blue);
}
&.gray {
@include button-color($gray);
}
&.pink {
@include button-color($pink);
}
& + & {
margin-left: 1rem;
}
&.fullWidth {
width: 100%;
justify-content: center;
& + & {
margin-left: 0;
margin-top: 1rem;
}
}
}
App.js
import React from 'react'
import Button from '../components/Button'
import SampleCss from '../components/Sample.scss'
export function Sample() {
return (
<div className="Sample">
<div className="buttons">
<Button color="blue" size="small" text="유닛등록"></Button>
<Button text="유닛등록"></Button>
<Button size="large" text="유닛등록"></Button>
</div>
<div className="buttons">
<Button color="gray" size="small" text="유닛등록"></Button>
<Button color="gray" text="유닛등록"></Button>
<Button color="gray" size="large" text="유닛등록"></Button>
</div>
<div className="buttons">
<Button color="pink" size="small" text="유닛등록 "></Button>
<Button color="pink" text="유닛등록"></Button>
<Button color="pink" size="large" text="유닛등록"></Button>
</div>
<div className="buttons">
<Button color="pink" size="small" text="유닛등록" outline></Button>
<Button color="blue" text="유닛등록" outline></Button>
<Button color="gray" size="large" text="유닛등록" outline></Button>
</div>
<div className="buttons">
<Button color="pink" size="small" text="유닛등록" fullWidth></Button>
<Button color="blue" text="유닛등록" outline fullWidth></Button>
<Button color="gray" size="large" text="유닛등록" fullWidth></Button>
</div>
</div>
)
}
export default Sample
이쁘다 이뻐~~
...rest props 전달하기
이제 우리가 버튼 컴포넌트는 다 만들었다. 만약 이 컴포넌트에 onClick을 설정해주고 싶다면 어떻게 해야할까 ?
Button.js 컴포넌트에 필요한 이벤트가 있을때마다 매번 이벤트를 추가하는 것은 비효율적이다.
이러한 이슈를 해결해줄수 있는 것이 spread와 rest이다.
이 문법은 주로 배열과, 객체, 함수의 파라미터 인자를 다룰때 사용하나, 컴포넌트에서도 사용할수 있다 !
Button.js를 다음과 같이 수정해보자 ~
Button.js
import React from 'react'
import './Button.scss'
import classNames from 'classnames'
export function Button({ text, size, color, outline, fullWidth, ...rest }) {
return (
<button
className={classNames('Button', size, color, { outline, fullWidth })}
{...rest}
>
{text}
</button>
)
}
Button.defaultProps = {
size: 'medium',
color: 'blue',
}
export default Button
App.js
import React from 'react'
import Button from '../components/Button'
import SampleCss from '../components/Sample.scss'
export function Sample() {
return (
<div className="Sample">
<div className="buttons">
<Button
color="blue"
size="small"
text="유닛등록"
onClick={() => {
console.log('OnClick!!!')
}}
></Button>
<Button text="유닛등록"></Button>
<Button size="large" text="유닛등록"></Button>
</div>
<div className="buttons">
<Button color="gray" size="small" text="유닛등록"></Button>
<Button color="gray" text="유닛등록"></Button>
<Button color="gray" size="large" text="유닛등록"></Button>
</div>
<div className="buttons">
<Button color="pink" size="small" text="유닛등록 "></Button>
<Button color="pink" text="유닛등록"></Button>
<Button color="pink" size="large" text="유닛등록"></Button>
</div>
<div className="buttons">
<Button color="pink" size="small" text="유닛등록" outline></Button>
<Button color="blue" text="유닛등록" outline></Button>
<Button color="gray" size="large" text="유닛등록" outline></Button>
</div>
<div className="buttons">
<Button color="pink" size="small" text="유닛등록" fullWidth></Button>
<Button color="blue" text="유닛등록" outline fullWidth></Button>
<Button color="gray" size="large" text="유닛등록" fullWidth></Button>
</div>
</div>
)
}
export default Sample
이렇게 ...rest를 사용해서 우리가 지정한 props를 제외한 값들을 rest라는 객체에 모아주고, 버튼 태그에 ...rest를 해주면 rest안에 있는 객체들의 값들을 모드 button에 설정해준다.
추후 비슷하게 어떤 props를 받을지는 모르지만 다른 컴포넌트 또는 HTML태그에 전달해야할 때 ...rest를 사용하도록 하자 ~~
고생하셨슴다 모두 !
1. Sass · GitBook
01. Sass Sass (Syntactically Awesome Style Sheets: 문법적으로 짱 멋진 스타일시트) 는 CSS pre-processor 로서, 복잡한 작업을 쉽게 할 수 있게 해주고, 코드의 재활용성을 높여줄 뿐 만 아니라, 코드의 가독성을
react.vlpt.us