Week 7. SCSS
내가 좋아하는 SCSS! 기초를 다시한 번 잡고 가즈아~!~!
널 좋아하는데... 좋아하지 않아... 아니 좋아해...아니 좋아하지 않아....
CSS Preprocessor(전처리 도구)
: 전처리 도구는 웹 브라우저에서 직접 동작하지 않기 때문에
node.js환경을 통해 CSS로 변환작업을 거쳐야 함.
Sass
:
SCSS
:
기본주석
: / 내용 /
컴파일되지 않는 주석
: // 내용
@at-root
유효범위 내에서 중첩을 벗어나야 할 때
.container {
.item {
$variable: 100px;
@at-root .box {
width: $variable;
}
}
}
.item 내부에서 선언됐지만 중첩을 벗어나서 컴파일됨.
.container {
flex: {
grow: 1; /* flex-grow: 1 */
shrink: 0; /* flex-shrink: 1 */
basis: auto; /* flex-basis: auto */
}
}
중첩에서 쉼표(,)로 다중선택 하게 되면 다중선택된 개수만큼 선택됨.
🧐 먼말인지 모르겠다면 예시
변수는 유효범위({}
)를 갖는다.
.container {
$inner: 200px !global;
width: $inner;
}
.box {
height: $inner;
}
⚠️ 이미 전역으로 사용하는 변수가 있을 때,
같은 이름의 지역변수가 덮어쓰지 않도록 주의
$primary: blue;
.container {
$primary: orange
}
변수는 재할당되기 때문에 $primary 변수가 orange로 재할당됨.
$primary: blue;
.container {
$primary: orange !default;
}
유효범위에 변수가 있다면 !default로 무시하고 없을 경우 !default 앞의 값을 할당
평가돼야 할 값이 있을 때
$list1: (10px, 20px, 30px);
$list2: 10px, 20px, 30px; /*소괄호 붙이지 않아도 됨*/
$list3: 10px 20px 30px; /*쉼표 안써도 됨*/
$map1: ( key, value );
$map2: (a: apple, b: banana, c: cherry);
map 값을 불러오려면 코드 상단부에서 코드 모듈을 불러와야 함.
@use 'sass:map'
;
값 가져오기: map.get(map 이름, 키값)
JS와 연산자가 비슷하지만 몇가지 주의사항이 있음.
$temp = 20px;
top: 20px / 2 👉 연산되지 않음
top: (20px / 2) /* 1. 소괄호로 묶어주기 */
top: $temp / 2 /* 2. 변수에 담아 계산하기 */
background-position: 100px 100px;
background-size: 200px 200px;
background: 100px 100px / 200px 200px; 👉🏻 단축 속성 구분
CSS에서 /
로 속성을 구분하는 것과 나머지 연산자(/)
와 겹침
.container {
$w: 100px;
$h: 200px;
$f: false;
@if (not $f or $h > 100px) {
width: $w;
height: $h;
}
}
if (condition, true, false)
font-size: if($size < 30px, 30px, $size)
@mixin large-text($size: 30px) { /* 매개변수 기본 값 */
font-size: $size; /* 40px */
font-weight: bold;
font-family: sans-serif;
}
.container {
@include larget-text(40px);
}
매개변수로 받은 값을 조건문으로 나눌 수 있다.
@mixin large-text($size: 30px) { /* 매개변수 기본 값 */
@if ($size < 30px) {
font-size: 30px; /* 매개변수가 30px보다 작으므로 30px로 들어감 */
} @else {
font-size: $size
}
font-weight: bold;
font-family: sans-serif;
}
.container {
@include larget-text(10px);
}
JS의 나머지 매개변수(rest parameter)와 유사함.
입력한 인수의 개수가 불확실할 때.
@mixin bg($w, $h, $url...) {
width: $w;
height: $h;
background: $url;
}
/* $url은 인수의 개수 상관없이 받음 */
.container {
@include bg(
100px,
200px,
url('/images/a.png') no-repeat center, /*z-index 가장 높음*/
url('/images/b.png') repeat-x, /* z-index 그 다음으로 높음 */
url('/images/c.png') repeat-y center / contain, /* z-index 가장 낮음 */
)
}
@mixin spread($top, $right, $bottom, $left) {
margin: {
top: $top;
right: $right;
bottom: $bottom;
left: $left;
}
}
.container {
$margin: 10px 20px 30px 40px; /* List 데이터 */
@include spread($margin...);
}
가변 인수를 사용하지 않을 경우,
첫번째 파라미터에만 list 데이터가 들어가게 됨.
인수를 순서에 상관없이 넣고 싶을 때
@mixin pos ($position, $top: null, $bottom: null, $left: null, $right: null) {
position: $position;
top: $top;
bottom: $bottom;
left: $left;
right: $right;
}
.container {
@include pos(absolute, $top: 100px, $left: 200px)
}
@include 호출 후 {} 안의 내용은 @content에 추가된다.
@mixin icon($url) {
&::after {
content: url($url);
@content; // 여기추가됨
}
}
.container {
@include icon('/images/icon.png') {
position: absolute;
top: 0;
left: 50px;
}
}
@content의 인수에 넣은 데이터는 mixin에 전달되어 using으로 받을 수 있다.
@content(밖으로 꺼낼 데이터)
@include 믹스인이름 using(받은 데이터)
👉 디버그 할 때 값 체크 용도로 쓸 수 있을 듯
@extend 선택자
.btn {
display: inline-block;
padding: 10px 20px;
background-color: blue;
}
.btn-primary {
@extend .btn;
font-weight: 700;
}
⚠️ @extend를 중첩 코드 내부에서 연속으로 사용하는 것을 지양해야 한다.
선택자 폭발
extend 전용 선택자
%btn {
display: inline-block;
padding: 10px 20px;
font-weight: 700;
}
.btn-primary {
@extend %btn;
background-color: blue;
}
.btn-red {
@extend %btn;
background-color: red;
}
.btn-green {
@extend %btn;
background-color: green;
}
미디어 쿼리 내부에 placeholder가 선언이 되어있어야만,
해당 placeholder를 사용할 수 있음.
@media (max-width: 1400px) {
%btn {
color: red;
}
.box {
@extend %btn;
}
}
⚠️ extend는 이러한 제한 규칙이 많기 때문에, mixin으로 대체하는 것을 권장.
👉🏻 다만 mixin을 남용하면 용량 최적화 문제가 있으므로 Gzip 압축방식
을 같이 사용.
형태: @function 이름 () {}
호출: 이름()
@function으로 grid system 만들어보기
$columns-width: 1400px;
@function grid($col: 1, $total: 12) {
@if ($col > $total) {
@error '$col must be less than $total.';
}
@return $columns-width * $col / $total;
}
.container {
width: grid(); // 116.6666666667px
}
.container {
width: grid(13); // error
}
⚠️ 함수 이름의 중복을 피하기 위해 두 단어 이상으로 이름 조합하기
List와 Map 데이터를 반복할 때 사용
@use 'sass:list';
$sizes: 20px, 40px, 80px;
$fruits: (apple: 'A', banana: 'B', cherry: 'C');
// List
@each $size in $sizes {
$index: list.index($sizes, $size);
.icon-#{$index} {
width: $size;
height: $size;
}
}
// Map
@each $key, $value in $fruits {
.fruit-#{$key}::after {
content: $value;
}
}
@for $i from 1 through 3 { // 1 <= 3
.item {
width: 100px * $i;
}
}
@for $i from 1 to 3 { // 1 < 3
.item {
width: 100px * $i;
}
}
.box {
$i: 1;
$n: 8;
@while ($n > 0) {
내용
}
$i: $i + 1;
$n: $n - 2; // 종료조건
}
@use 'sass:'
@use './variables';
.container {
color: variables.$primary;
}
@import로 불러오지 않고, @use로 불러오게 되면 모듈로 불러오게 됨.
모듈.변수 등으로 이름 충돌없이 명확히 사용할 수 있음.
어떤 특정한 영역에서 사용하는 모듈을
해당 파일 밖으로 전달
@forward 모듈 as 이름-*
👉🏻 *에 모듈 내부의 변수들을 넣을 수 있음.
형태: @use sass:
@use 'sass:math'
math.ceil() /*올림*/
math.floor() /*내림*/
math.round() /*반올림*/
math.max() /*최대값*/
math.min() /*최소값*/
math.abs() /*절대값*/
math.is-unitless(20px) /*결과: false, 단위가 없는지 확인*/
math.is-unitless(20) /*결과: true, 단위가 없는지 확인*/
math.compatible(비교값1, 비교값2) /*연산이 가능한지 확인 = 단위가 같음?*/
@use 'sass:string';
string.quote(); /*따옴표 추가*/
string.unquote(); /*따옴표 제거*/
string.index(문자열, 찾을 문자열);
string.insert(문자열, 넣을 문자열, index);
string.length(문자열);
string.slice(문자열, 자를 인덱스); /*잘라진 문자열이 반환됨*/
string.to-upper-case(문자열);
string.to-lower-case(문자열);
string.unique-id(); /*유니크한 문자 데이터를 만들어줌*/
/*전역 함수*/
darken($color, $amount);
lighten($color, $amount);
/*모듈*/
@use 'sass:color';
선택자: {속성: color.adjust($color, $lightness: $amount)}
/*전역 함수*/
saturate($color, $amount)
desaturate($color, $amount)
/*모듈*/
@use 'sass:color';
선택자: {속성: color.adjust($color, $saturation: $amount)}
/*전역 함수*/
grayscale($color)
/*모듈*/
@use 'sass:color';
선택자: {속성: color.grayscale($color)}
⚠️ list의 index는 1부터 시작
@use 'sass:list';
list.append(list, element) /* append된 list 반환 */
list.index(list, element) /*element의 index 반환*/
list.index(list, element) /*element의 index 반환*/
list.join(list, list2) /*요소들이 합쳐진 list 반환*/
list.length(list) /*list의 length 반환*/
list.nth(list, index) /*list[index] 반환*/
@use 'sass:map';
map 이름: (키: 값, 키: 값)
map.get(map 이름, 키);
map.has-key(map 이름, 키);
map.keys(map 이름); /*키를 list로 반환*/
map.values(map 이름); /*키 값을 list로 반환*/
map.merge(map 이름, map2 이름) /*map 합치고 반환 👉🏻 키 중복 안됨*/
map.remove(map 이름, 키) /*복사된 새 map의 프로퍼티 삭제 후 반환*/
@use 'sass:meta';
meta.call($callback, 인수); /*콜백함수에 인수를 넣어 실행*/
meta.type-of(값) /*타입 체크*/
@debug /*console.log*/
@warn /*console.warn*/
@error /*throw error*/
와... 죽겠다............