Sass(Syntactically Awesome Style Sheets)
: CSS pre-processor(CSS전처리도구, CSS전처리기) 로서, 코드의 재활용성과 가독성을 높여주어 유지보수를 용이하게 해준다.
$ yarn add node-sass
✍️ Sass와 SCSS의 차이점은?
SCSS의 주석
/* */
//
//
은컴파일 과정에서 css로 변환된 결과로 나타나지 않는다. 따라서 변환된 후에도 주석이 남아있어야 한다면 표준 /* */
주석을 사용한다.자식요소 선택하기
>
를 이용한다.
// ex.)
.container {
> ul {
li {
.name {
color: rgb(102, 105, 255);
}
.age {
color: rgb(38, 179, 132);
}
}
}
}
상위(부모) 선택자 참조
&
를 이용한다.
// ex.)
.btn {
padding: 5px 15px;
&.active {
color: red;
}
}
중첩 속성
font-
, margin-
, padding-
등과 같이 동일한 네임 스페이스를 가지는 속성들에 다음과 같이 사용할 수 있다. (네임스페이스가 동일하다 → 어떤 속성이 가지고 있는 이름부분의 영역이 동일하다)// ex.)
.box {
font: {
weight: bold;
size: 10px;
family: sans-serif;
};
margin: {
top: 10px;
left: 20px;
};
padding: {
bottom: 40px;
right: 30px;
};
}
변수설정
$
를 이용한다.
{}
밖과 {}
안에서 같은 변수를 새롭게 재정의할 수 있고, 블록 범위 아래에서 영향을 미친다. (재할당 가능)$size: 100px;
산술연산
calc()
함수를 사용하면 다른 단위라도 연산이 가능하다. width: calc(100% - 200px)
재활용하기
@mixin
과 @include
키워드와 함께 이름을 붙여서 사용한다.내장함수
mix()
: 첫번째 인수와 두번째 인수를 섞어서 새로운 색상을 표현한다.$color: royalblue;
background-color: mix($color, pink); // 연보라색
lighten()
& darken()
: 첫 번째 인수에 특정 색상을 입력, 두 번째 인수에 수치를 입력한다. 해당컬러의 명도를 조절한다.background-color: lighten($color, 30%); // 첫 번째 인수의 색상을 30% 밝게 한다.
saturate()
& desaturate()
: 해당 컬러의 채도를 조정한다.background-color: desaturate($color, 30%);
grayscale()
: 해당 컬러의 톤에서 그레이스케일로 변환한다.background-color: grayscale($color);
invert()
: 해당 컬러를 반전시킨다.background-color: invert($color);
rgba()
: 해당 컬러의 투명도를 조절한다.background-color: rgba($color, 0.5); // 50% 만큼 불투명 (반투명)
조건부 스타일링을 할 때 함수의 인자에 문자열, 배열, 객체 등을 전달하여 손쉽게 문자열을 조합 할 수 있게 해준다.
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와 같이 falsy한 값들은 무시된다.
classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // 'bar 1'
✍️ 위와 같이 classnames의 도움을 받지 않을 경우엔 아래처럼 동적으로 클래스 이름을 넣을 수 있겠다.
// size로 medium이 넘어올 경우
function Button({ children, size }) {
return <button className={['Button', size].join(' ')}>{children}</button>;
} // Button medium
// className={`Button ${size}`} 혹은 이렇게 받아온다.
ex) 예시 ▼
// Button.jsx
function Button({ children, size, color, outline }) {
return (
// props로 받아와서 객체 안에 넣음 ▼
// outline 값이 true 일 때에만 button 에 outline CSS 클래스가 적용된다.
<button className={classNames('Button', size, color, { outline })}>
{children}
</button>
);
}
// App.js
<div className='buttons'>
<Button size='large' outline> BUTTON </Button>
<Button color='pink'>BUTTON</Button> // outline X
<Button size='small' color='violet' outline> BUTTON </Button>
</div>
// button.scss
$blue: #228be6;
$pink: #ff8787;
$violet: #b197fc;
@mixin button-color($color) { // 2)
background: $color;
&:hover {
background: ligthen($color, 10%); // 색상 10% 밝게 해주는 함수
}
&:active {
background: darken($color, 10%); // // 색상 10% 어둡게 해주는 함수
}
&.outline {
color: $color;
background: none;
border: 1px solid $color;
&:hover {
background: $color;
color: white;
}
}
}
.Button {
color: white;
font-weight: bold;
outline: none;
border-radius: 4px;
border: none;
cursor: pointer;
// 사이즈 관리
&.large {
// .button.large 를 의미한다. (선택자1과 선택자2 모두만족)
height: 3rem;
padding-left: 1rem;
padding-right: 1rem;
font-size: 1.25rem;
}
&.medium {
...
}
&.small {
...
}
// 색상 관리
&.blue {
@include button-color($blue);
}
&.pink {
...
}
&.violet {
...
}
& + & { // 1)
margin-left: 1rem;
}
}
1) & + &
가 의미 하는 것은 .Button + .Button
이다. 만약 함께 있다면 우측에 있는 버튼에 여백을 설정 한 것이다. (제일 좌측은 여백이 그대로인데, 이렇게 나란히 있을 때 사용하기 좋을 것 같다! 😀 )
2) @mixin
반복이 되는 코드는 Sass 의 mixin
이라는 기능을 사용하여 쉽게 재사용 할 수 있다.
컴포넌트를 스타일링 할 때 CSS Module 을 사용하면, CSS 클래스가 중첩되는 것을 방지할 수 있다.
import './App.css';
import './App.scss';
이러한 단점을 극복하기 위해서 webpack을 이용해서 스코프가 오염되지 않는 형태로 자동으로 도움을 주는 기능이 추가된 형태의 css 모듈을 사용한다.
- webpack 에서 제공하는 css-loader에서 지원이 되며, CRA로 만든 프로젝트일 경우 이미 적용이 되어 있어서 별도로 설치하지 않아도 된다. 😀
- CRA 로 만든 프로젝트에서 CSS Module 를 사용 할 때에는, CSS 파일의 확장자를 .module.css 로 한다.
import styles from './App.module.css';
import styles from './App.module.scss';
css모듈을 사용하면 실제 작성했던 css 코드를 변환을 시킨 후 스타일에 (전역으로) 추가해준다.
css 클래스 이름이 만들어지는 과정에서는 파일 경로, 파일 이름, 클래스 이름, 해쉬값 등이 사용 될 수 있다.
▶ [filename]\_[classname]\_\_[hash]
형식의 고유한 클래스 이름을 자동으로 생성하고 매칭시켜준다. → 이름이 충돌되지 않도록 돕는다.
즉, css-module을 이용하면 클래스명이 충돌하는 일반적인 css단점을 극복할 수 있게 된다.
styles.name
과 같이 import로 불러온 styles
객체 안에 있는 값을 참조한다.-
가 있다면 styles[class-name]
과 같이 사용한다.${style.a} ${style.b}
과 같이 작성한다.classnames
라이브러리 활용하기조건부 스타일링을 할 경우 classnames
라이브러리 도움을 받을 수 있다.
classnames
의 bind
기능을 사용하면, 이름을 지정해 줄 때 cx('클래스이름')
과 같은 형식으로 편하게 사용 할 수 있다. 여러개의 CSS 클래스를 사용해야 하거나, 조건부 스타일링에 사용된다.
// ${styles.one} ${condition ? styles.two : ''} 와 같이 사용하는 것 대신
import classNames from 'classnames/bind';
const cx = classNames.bind(styles);
cx('one', 'two')
cx('my-component', {
condition: true
})
cx('my-component', ['another', 'classnames'])
console.log(styles)
콘솔에 출력해보자.
{
App: "App_App__B2Ebb"
App-logo-spin: "App_App-logo-spin__1up6W"
header: "App_header__fhC8n"
link: "App_link__kpF6Q"
logo: "App_logo__7Edbg"
}
위와 같은 객체가 출력되는 것을 볼 수 있다. 🤔
→ 따라서 styles로 부터 얻어낸 값을 사용하기 위해서 JSX문법으로 해당key를 주면 아래처럼 작성해 볼 수 있다.
// 초기 App 컴포넌트에서 css모듈 설정
function App() {
return (
<div className={styles.App}>
<header className={styles.header}>
<img src={logo} className={styles.logo} alt='logo' />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className={styles.link}
href='https://reactjs.org'
target='_blank'
rel='noopener noreferrer'
>
Learn React
</a>
</header>
</div>
);
}
CSS Module 을 사용하고 있는 파일에서 클래스 이름을 고유화 하지 않고 전역적 클래스이름을 사용하고 싶을 땐 아래와 같이 사용한다.
// css
:global .my-global-name {
}
// scss
:global {
.my-global-name {
}
}
CSS Module 을 사용하지 않는 곳에서 특정 클래스에서만 고유 이름을 만들어서 사용하고 싶다면 아래와 같이 사용한다.
// css
:local .make-this-local {
}
// scss
:local {
.make-this-local {
}
}
✍️ JavaScript에서 CSS를 적용할 때 SCSS를 사용해 보았는데 React에서는 어떻게 적용해야 하는지 궁금했던 점을 알 수 있었다.(CRA 정말 편하다👍)
styles를 통해 CSS를 적용하는 부분이나 classnames 라이브러리를 통해 스타일을 적용하는 부분은 자주 접해보면서 익숙해져야겠다.🧐
reference)
heropy - scss
vlpt-react styling
fastcapmus