FrontEnd

Sass(Scss)

hjkang

Sass(Scss)란?

  • Sass는 CSS 전처리기로서 CSS의 한계와 단점을 보완하여 보다 가독성이 좋고 코드 재사용에 있어서 유리하다.
  • CSS 문법과 유사하지만 선택자의 중첩이나 조건문, 반복문, 연산 등 여러 기능을 사용해서 더 편리하게 작성할 수 있다.
  • 2006년부터 시작하여 가장 오래된 css 확장 언어이며 그만큼 많은 커뮤니티를 가지고 있다.

 

Sass와 Scss의 차이

  • Scss는 Sass의 세 번째 버전에서 추가되었고 Sass의 모든 기능을 지원하면서 Css와 거의 같은 문법을 사용한다.
  • Scss는 Css처럼 중괄호와 세미콜론을 사용하지만 Sass는 들여쓰기만 사용한다.
  • Mixins(재사용 가능한 기능)을 사용하는 경우 Sass는 =와 + 기호로 기능을 사용하지만 Scss는 @mixin과 @include 지시자로 사용한다.
  • Sass는 코드를 간략화할 수 있는 장점이 있지만 Css와 비슷한 Scss를 사용하는 경우가 더 많다.

Sass:

.list
  width: 100px
  float: left
  li
    color: red
    background: url("./image.jpg")

Scss:

.list {
  width: 100px;
  float: left;
  li {
    color: red;
    background: url("./image.jpg");
  }
}
 



Mixins 기능

Sass:

=box-style
  width: 100px
  height: 50px
  background-color: blue

.box
  +box-style

Scss:

@mixin box-style{
  width: 100px;
  height: 50px;
  background-color: blue;
}
.box {
  @include box-style;
}
 



컴파일

  • 웹에서는 css만 동작하므로 sass를 사용하기 위해서는 css로 컴파일하는 과정이 필요하다.
  • 간단한 scss 코드는 컴파일러 설치하는 게 부담될 수 있으니 https://www.sassmeister.com/ 에서 실시간으로 변환할 수 있다.
  • 노드 환경에서는 node-sass를 사용하여 컴파일할 수 있다.
node-sass [옵션] <입력파일경로> [출력파일경로]
node-sass scss/main.scss public/main.css



구문과 문법

 

# 중첩(Nesting): 상위 선택자의 반복 선언을 피할 수 있다.

Scss:

.section {
  width: 100%;
  .list {
    padding: 20px;
    li {
      float: left;
    }
  }
}

css:

.section {
  width: 100%;
}
.section .list {
  padding: 20px;
}
.section .list li {
  float: left;
}
 



# 상위 선택자 참조: 중첩 안에서 & 키워드는 상위 선택자를 참조하여 치환한다.

Scss:

.btn {
  position: absolute;
  &.active {
    color: red;
  }
}

.list {
  li {
    &:last-child {
      margin-right: 0;
    }
  }
}

css:

.btn {
  position: absolute;
}
.btn.active {
  color: red;
}
.list li:last-child {
  margin-right: 0;
}
 

 

& 키워드가 참조한 상위 선택자로 치환되는 것이기 때문에 아래처럼 응용할 수도 있다.

Scss:

.fs {
  &-small { font-size: 12px; }
  &-medium { font-size: 14px; }
  &-large { font-size: 16px; }
}

css:

.fs-small {
  font-size: 12px;
}
.fs-medium {
  font-size: 14px;
}
.fs-large {
  font-size: 16px;
}
 



# 중첩된 속성: font-, margin- 등과 같이 동일한 네임 스페이스를 가지는 속성의 경우 다음과 같이 사용할 수 있다.

Scss:

.box {
  font: {
    weight: bold;
    size: 10px;
    family: sans-serif;
  };
  margin: {
    top: 10px;
    left: 20px;
  };
  padding: {
    bottom: 40px;
    right: 30px;
  };
}

css:

.box {
  font-weight: bold;
  font-size: 10px;
  font-family: sans-serif;
  margin-top: 10px;
  margin-left: 20px;
  padding-bottom: 40px;
  padding-right: 30px;
}
 



# 변수: 반복적으로 사용되는 값을 변수로 지정할 수 있다. 변수 앞에는 항상 $ 기호를 붙인다.

Scss:

$color-primary: #e96900;
$url-images: "/assets/images/";
$w: 200px;

.box {
  width: $w;
  background: $color-primary url($url-images + "bg.jpg");
}

css:

.box {
  width: 200px;
  margin-left: 200px;
  background: #e96900 url("/assets/images/bg.jpg");
}
 



# 변수 재할당: 변수에 변수를 할당할 수 있다.

Scss:

$red: #FF0000;
$blue: #0000FF;

$color-primary: $blue;
$color-danger: $red;

.box {
  color: $color-primary;
  background: $color-danger;
}

css:

.box {
  color: #0000FF;
  background: #FF0000;
}
 



# 문자 보간: #{} 를 이용해서 어디든지 변수 값을 넣을 수 있다.

Scss:

$family: unquote("Droid+Sans");
@import url("http://fonts.googleapis.com/css?family=#{$family}");
 

* unquote()는 Sass의 내장 함수로 문자에서 따옴표를 제거한다.

 

css:

@import url("http://fonts.googleapis.com/css?family=Droid+Sans");
 



# 연산: 기본적인 연산 기능을 지원한다. 

- 만약 상대적 단위(%, em 등)를 연산하는 경우 calc()를 사용해야 한다. ex) width: calc(50% - 20px);

Scss:

div {
  width: 20px + 20px;
  height: 40px - 10px;
  font-size: 10px * 2;
  margin: (30px / 2);
}

css:

div {
  width: 40px;
  height: 30px;
  font-size: 20px;
  margin: 15px;
}
 



# 색상 연산

Scss:

div {
  color: #123456 + #345678;
  background: rgba(50, 100, 150, .5) + rgba(10, 20, 30, .5);
}

css:

div {
  color: #468ace;
  background: rgba(60, 120, 180, 0.5);
}
 



# Mixins: 재활용 할 css를 정의하는 기능으로 함수처럼 인수를 가질 수 있고, 인수는 기본값을 가질 수 있다.

Scss:

@mixin dash-line($width, $color: blue) {
  border: $width dashed $color;
}

.box1 { @include dash-line(1px, red); }
.box2 { @include dash-line(4px); }

css:

.box1 {
  border: 1px dashed red;
}
.box2 {
  border: 4px dashed blue;
}
 



# 확장: 특정 선택자가 다른 선택자의 모든 스타일을 가질 수 있다.

Scss:

.btn {
  padding: 10px;
  margin: 10px;
  background: blue;
}
.btn-danger {
  @extend .btn;
  background: red;
}

css:

.btn, .btn-danger {
  padding: 10px;
  margin: 10px;
  background: blue;
}
.btn-danger {
  background: red;
}
 



# 함수: 믹스인과 거의 유사하지만 반환되는 내용이 다르다.

- 믹스인은 지정한 스타일을 반환하는 반면 함수는 보통 연산된 특정 값을 @return 지시어를 통해 반환한다.

Scss:

$max-width: 980px;

@function columns($number: 1, $columns: 12) {
  @return $max-width * ($number / $columns)
}

.box_group {
  width: $max-width;

  .box1 {
    width: columns();
  }
  .box2 {
    width: columns(8);
  }
  .box3 {
    width: columns(3);
  }
}

css:

.box_group {
  /* 총 너비 */
  width: 980px;
}
.box_group .box1 {
  /* 총 너비의 약 8.3% */
  width: 81.66667px;
}
.box_group .box2 {
  /* 총 너비의 약 66.7% */
  width: 653.33333px;
}
.box_group .box3 {
  /* 총 너비의 25% */
  width: 245px;
}
 




# 조건문

- if (함수): 조건의 값(true, false)에 따라 하나만 반환한다.

  조건이 true면 표현식1을, false면 표현식2를 반환한다. - if(조건, 표현식1, 표현식2)

Scss:

$width: 555px;
div {
  width: if($width > 300px, $width, null);
}

css:

div {
  width: 555px;
}
 



- @if (지시어): 조건(and, or, not 가능)에 따른 분기 처리가 가능하며 if문과 유사하다.

Scss:

$color: orange;
div {
  @if $color == strawberry {
    color: #FE2E2E;
  } @else if $color == orange {
    color: #FE9A2E;
  } @else if $color == banana {
    color: #FFFF00;
  } @else {
    color: #2A1B0A;
  }
}

css:

div {
  color: #FE9A2E;
}
 



# 반복문: 스타일을 반복적으로 출력한다.

 

@for: for문과 유사하다. through를 사용하면 종료값만큼 반복하고 to를 사용하면 종료 직전까지 반복한다.

Scss:

// 1부터 3번 반복
@for $i from 1 through 3 {
  .through:nth-child(#{$i}) {
    width : 20px * $i
  }
}

// 1부터 3 직전까지만 반복(2번 반복)
@for $i from 1 to 3 {
  .to:nth-child(#{$i}) {
    width : 20px * $i
  }
}

css:

.through:nth-child(1) { width: 20px; }
.through:nth-child(2) { width: 40px; }
.through:nth-child(3) { width: 60px; }

.to:nth-child(1) { width: 20px; }
.to:nth-child(2) { width: 40px; }
 



@each: for in 문과 유사하다. List, Map 데이터를 반복할 때 사용한다.

$fruits: (apple, orange, banana, mango);

.fruits {
  @each $fruit in $fruits {
    li.#{$fruit} {
      background: url("/images/#{$fruit}.png");
    }
  }
}

css:

.fruits li.apple {
  background: url("/images/apple.png");
}
.fruits li.orange {
  background: url("/images/orange.png");
}
.fruits li.banana {
  background: url("/images/banana.png");
}
.fruits li.mango {
  background: url("/images/mango.png");
}
 

참고

'FrontEnd' 카테고리의 다른 글

React.js - useEffect 훅  (1) 2023.10.29
NestJS - Query Params로 배열 받기(DTO 사용)  (0) 2023.08.10
NextJS - 클라이언트 사이드에서 쿠키 저장  (0) 2023.08.06
React Native  (0) 2023.01.06
프론트엔드 성능 최적화  (0) 2022.10.23