[Scss] Nesting & @Rules & 조건과 반복 & Mixin & Function

유동균·2023년 1월 27일
0

Scss

목록 보기
3/4
post-thumbnail

1. Nesting

  • Nesting은 Sass의 유용한 확장 기능으로 선언을 중첩(nesting)하는 것이다.
  • CSS는 후손 셀렉터(Descendant combinator)의 경우 부모요소를 기술하여야 하지만
nav {
  width: 100%;
  height: 30px;
}
nav ul {
  list-style-type: none;
}
nav li {
  display: flex;
}
nav li a {
  text-decoration: none;
}
  • Sass의 nesting을 사용하면 후손 셀렉터를 간단히 기술할 수 있다.
nav {
  width: 100%;
  height: 30px;

  ul {
    list-style-type: none;
  }

  li {
    display: flex;
    a {
      text-decoration: none;
    }
  }
}
  • 깊은 nesting은 가독성을 나쁘게 하고 셀렉터를 복잡하게 만들기 때문에 사용에 주의하자.

  • 부모 요소의 참조가 필요한 경우 &를 사용한다. 예를 들어, :hover 또는 ::before 등의 가상 클래스 선택자 (Pseudo-class selector)를 지정하는 경우 부모 요소의 참조가 필요하다.

// main.scss
.link {
  color: red;
  
  // 프로퍼티의 nesting
  font : {
    family: "Courier New";
    size: 24px;
    weight: bold;
  }

  &:hover {
    background-color: green;
  }

  &:visited {
    color: blue;
  }
}
// main.css
.link {
  color: red;
  font-family: "Courier New";
  font-size: 24px;
  font-weight: bold;
}
.link:hover {
  background-color: green;
}
.link:visited {
  color: blue;
}

2. @-Rules and Directives

  • 1개의 CSS 파일에 모든 스타일을 기술하면 유지보수하기 힘들고 가독성이 좋지 않기 때문에 css 파일을 분리하여 사용한다.
  • css 파일을 분리하여 사용할 경우 재사용성이 좋고, 유지 보수가 유리하다.
  • 여러 개의 파일로 분할하는 것 또는 분할된 파일을 partial이라고 하며 partial된 Scss 파일명 앞에는 underscore(_)를 붙인다. (_header.scss)
  • partial 된 Scss 파일명의 underscore는 import는 수행하면서 트랜스파일링은 수행하지 말라는 의미.

2.1 @import

@import "header";  // .scss 확장자는 생략 가능

@import "main", "footer"; // 여러개의 파일 import 가능


$family: "Open+Sans"; // 변수를 사용해 import 가능
@import url("http://fonts.googleapis.com/css?family=#{$family}");
// partial/_vars.scss
$width: 375px;
// partial/_header.scss
header {
  width: $width;
}
// partial/_section.scss
section {
  width: $width;
}
// partial/_footer.scss
footer {
  width: $width;
}
// style.scss
@import "partial/vars";
@import "partial/header";
@import "partial/section";
@import "partial/footer";
  • _vars.scss에는 변수가 선언되어 있으므로 partial된 _vars.scss, _header.scss, _sidebar.scss, _footer.scss를 import가 수행되어 하나의 파일이 되기 이전에 트랜스파일링을 실행하면 에러가 발생. 즉, partial된 Sass 파일명 선두에 붙인 _을 제거하면 에러가 발생한다.

  • @import의 단점

    • variables, mixins, functions 전역 스코프로 사용되다 보니 이름이 겹칠 가능성이 커서 이름이 중복되지 않도록 작성해야 합니다.
    • 사용된 variables, mixins, functions 어느 파일에서 선언되었는지 추적하기 어렵다.

2.2 @use

  • @use는 namespace로 사용되어진다.
  • @import 대체되는 문법으로 variables, mixins, functions를 연결하는 용도로 사용되고 @import와 동일하게 스타일시트 최상단에 연결한다.
  • @use를 여러 번 하더라도 컴파일된 CSS 파일은 한 번만 표시되어 @import에 비해 컴파일 시간이 짧습니다.
// main.scss
// _buttons.scss 파일 안의 $primary-color 변수 가져오기

@use "buttons";
.close {
	color : buttons.$primary-color;	// 파일명.$변수명
}
  • 축약식
// main.scss

@use "buttons" as b;
.close {
	color : b.$primary-color;	// 파일명.$변수명
}
  • 생성한 변수명이 다른 파일에서 겹치더라도, 가져올 파일명을 정해줬기 때문에 문제가 생기지 않는다.

2.3 @forward

  • @use로 연결하는 파일이 여러 개인 경우, @forward로 모아서 그 해당 파일을 연결해 줄 수 있다.
// colors.scss
$red: red;
// fonts.scss
$font-size: 1.5rem;
// bootstrap.scss
@forward "colors";
@forward "fonts";
// styles.scss
@use "bootstrap";

.card {
  font-size: bootstrap.$font-size;
  color: bootstrap.$red;
}
  • @use는 불러온 스타일을 현재 파일(styles.scss)에서
    바로 사용하기 위해 필요한 문법
  • @forward는 여러 스타일을 bootstrap.scss로 불러와서 이를 다시, @use를 통해 style.scss에서 사용하는데 목적

2.4 @extend

  • 기존 스타일을 상속하려고 할 경우 사용한다.
<div class="error seriousError">
  Oh no! You've been hacked!
</div>
  • 기존에 선언되어 있는 error class를 사용하면서 일부 rule set에 대해서는 다른 선언이 필요한 경우 사용
.error {
  border: 1px #f00;
  background-color: blue;
}

.seriousError {
  @extend .error;

  border-width: 3px;
  border-color: darkblue;
}
  • 위 코드의 트랜스파일링 결과는 아래와 같다. .error와 .seriousError가 공통으로 사용하는 프로퍼티를 묶어 합리적인 룰셋을 생성한다.
.error, .seriousError {
  border: 1px #f00;
  background-color: blue;
}

.seriousError {
  border-width: 3px;
  border-color: darkblue;
}
  • 따라서 위의 html은 아래와 같이 작성할 수 있다.
<div class="seriousError">
  Oh no! You've been hacked!
</div>
  • @extend@media 블록과 같이 사용하는 경우, 제대로 작동하지 않는다. 다시 말해, @media 안에서 외부의 선택자를 @extend할 수 없다.
.foo {
  color: red;
}

@media print {
  .bar {
    @extend .foo; // ERROR: You may not @extend selectors across media queries.
  }
}

@extend를 사용하면 트랜스파일링 후 자신의 셀렉터가 어디에 첨부될 것인지 예상하기 어렵고, 예상치 못했던 부작용이 발생할 수 있다. 따라서 @extend의 사용은 가급적 자제하고 Mixin은 사용하는 것을 추천.

2.5 Placeholder Selectors

  • Placeholder Selector는 재사용이 가능한 rule set을 % 키워드로 지정하는 @extend 전용 Selector이다.

  • Placeholder Selector은 상속만을 위한 rule set으로 자신은 트랜스파일링되지 않는다.

%input-style {
  font-size: 14px;
}

.input-black {
  @extend %input-style;

  color: black;
}

.input-red {
  @extend %input-style;

  color: red;
}
  • 트랜스파일링 결과
.input-red, .input-black {
  font-size: 14px;
}

.input-black {
  color: black;
}

.input-red {
  color: red;
}

3. 조건과 반복

3.1 if()

if(condition, if_true, if_false)

  • built-in if() 함수는 주어진 조건을 판단하여 결과를 리턴한다. Javascript의 삼항연산자와 유사하게 동작
  • condition이 true이면 if_true를, false이면 if_false를 반환한다.
$type: ocean;

p {
  color: if($type == ocean, blue, black); // color: blue;
}
span {
  color: if($type == ocean1, blue, black); // color: black;
}

3.2. @if…@else

  • 조건 분기
$type: green;

p {
  @if ($type == blue) {
    color: blue;
  } @else if ($type == red) {
    color: red;
  } @else if ($type == green) {
    color: green;
  } @else {
    color: black;
  }
}
  • 트랜스파일링 결과
p {
  color: green;
}

3.3 @for

  • 반복문을 사용
  • @for 변수 from (start_Num) to (end_Num){...}
@for $i from 1 through 5 {
  .item-#{$i} {
    width: 16px * $i;
    height: 8px * $i;
  }
}
  • 트랜스파일링 결과
.item-1 {
  width: 16px;
  height: 8px;
}

.item-2 {
  width: 32px;
  height: 16px;
}

.item-3 {
  width: 48px;
  height: 24px;
}

.item-4 {
  width: 64px;
  height: 32px;
}

.item-5 {
  width: 80px;
  height: 40px;
}

3.4 @each

  • list와 map의 데이터를 반복할 때 사용
@each $변수 in 데이터 {
  실행문
}

하나의 데이터를 저장하기 위해 변수를 사용하는데, 여러 개의 데이터를 저장할 때에는 list 또는 map 형식으로 저장

  • list
//List Data
$fruits: (apple, banana, mango, orange);

.list_fruits {
  @each $fruit in $fruits {
    li.#{$fruit} {
      background: url("../img/#{fruit}.png");
    }
  }
}
  • list 트랜스파일링
.list_fruits li.apple {
  background: url("../img/fruit.png");
}
.list_fruits li.banana {
  background: url("../img/fruit.png");
}
.list_fruits li.mango {
  background: url("../img/fruit.png");
}
.list_fruits li.orange {
  background: url("../img/fruit.png");
}
  • map
    • 특징은 각 값마다 매칭 된 키가 있기 때문에 동적으로 접근할 수 있다.
// Map Data
$coffees: (
  mild: americano,
  soft: latte,
  strong: espresso,
  sweet: mocha,
);

@each $state, $menu in $coffees {
  #{$state}-icon {
    background: url("../img/#{$menu}.png");
  }
}
  • map 트랜스파일링 결과
mild-icon {
  background: url("../img/americano.png");
}

soft-icon {
  background: url("../img/latte.png");
}

strong-icon {
  background: url("../img/espresso.png");
}

sweet-icon {
  background: url("../img/mocha.png");
}

3.5 @while

  • 반복문을 사용
$i: 10;

@while $i > 0 {
  .item-#{$i} {
    width: 4px * $i;
  }
  $i: $i - 2;
}
  • 트랜스파일링 결과
.item-10 {
  width: 40px;
}

.item-8 {
  width: 32px;
}

.item-6 {
  width: 24px;
}

.item-4 {
  width: 16px;
}

.item-2 {
  width: 8px;
}

4. Mixin

  • Mixin은 Sass의 매우 유용한 기능으로 중복 기술을 방지하기 위해 사용 빈도가 높은 마크업을 사전에 정의하여 필요할 때에 불러 사용하는 방법이다.

  • @extend와 유사하나 프로그래밍 언어의 함수와 같이 인수를 전달받을 수 있다는 차이가 있음

  • @mixin 선언하고 @include로 불러오기

@mixin mixin-name {
  // code
}

@mixin mixin-name( $arg1, $arg2, ... ) {
  // code
}
// 지름이 100px인 원
@mixin circle {
  width: 100px;
  height: 100px;
  border-radius: 50%;
}

// 지름이 100px인 원을 위한 mixin을 include한 후 배경을 추가 지정
.box {
  @include circle;

  background: yellow;
}
  • 트랜스파일링 결과
.box {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: yellow;
}
  • @extend와 차이가 없어 보이나 Mixin은 함수와 같이 매개 변수를 사용 가능
@mixin circle($size) {
  width: $size;
  height: $size * 2;
  border-radius: 50%;
}

.box {
  @include circle(100px);

  background: #f00;
}
  • 매개 변수 사용 결과
.box {
  width: 100px;
  height: 200px;
  border-radius: 50%;
  background: #f00;
}
  • 매개 변수의 초기값을 설정
@mixin circle($size: 10px) {
  width: $size;
  height: $size * 2;
  border-radius: 50%;
}

.box {
  // 인수가 전달되지 않으면 초기값을 사용한다.
  @include circle();
  background: #f00;
}
  • 매개 변수의 초기값 결과
.box {
  width: 10px;
  height: 20px;
  border-radius: 50%;
  background: #f00;
}

5. Function

  • Function은 mixin과 유사하나 반환값에 차이가 있다.

    • mixin : style markup을 반환

    • function : @return directive를 통하여 값을 반환

$grid-width: 40px;
$gutter-width: 10px;

@function grid-width($n) {
  @return $n * $grid-width + ($n - 1) * $gutter-width;
}

#sidebar { width: grid-width(5); }
  • 트랜스파일링 결과
#sidebar {
  width: 240px;
}

6. Comment

  • CSS는 멀티 라인 주석 /* */만을 지원하지만 Sass는 /* */// 모두 사용할 수 있다.

  • 한 줄 주석 //은 트랜스파일링 후 CSS에서 사라지고, 멀티 라인 주석은 CSS에 나타난다.

0개의 댓글