SCSS(SASS) 정리 2-1

July 15, 2021

SCSS(SASS)는 어떤 기능들을 지원할까? 2-1

SCSS(SASS)에서 제공하는 기능들에 대해 알아보겠습니다.

SCSS와 SASS의 차이점

단순한 몇가지를 제외하면 차이가 거의 없습니다.

  • SCSS는 SASS(Syntactically Awesome Style Sheets)의 3버전에서 새롭게 등장했습니다.
  • SCSS는 CSS구문과 완전히 호환되도록 새로운 구문을 도입해서 만든 SASS의 모든 기능을 지원하는 CSS의 상위집합(Superset) 입니다.
  • 쉽고 간단한 차이로는 {}(중괄호)와 ;(세미콜론)의 유무가 있습니다.

정리해보면

SCSS는 CSS와 거의 같은 문법으로 Sass 기능을 지원한다.

입니다.

아래 예제를 비교해 보세요.

작성 방법

SASS :

.list
  width: 100px
  float: left
  li
    color: red
    background: url("./image.jpg")
    &:last-child
      margin-right: -10px

SASS - 선택자의 유효범위를 들여쓰기로 구분

SCSS :

.list {
  width: 100px;
  float: left;
  li {
    color: red;
    background: url("./image.jpg");
    &:last-child {
      margin-right: -10px;
    }
  }
}

SCSS - 선택자의 유효범위를 {}로 구분

Mixins(재사용 가능한 기능을 만드는 방식)

SASS :

=border-radius($radius)
  -webkit-border-radius: $radius
  -moz-border-radius:    $radius
  -ms-border-radius:     $radius
  border-radius:         $radius

.box
  +border-radius(10px)

SASS - =+기호로 Mixins 기능 사용

SCSS :

@mixin border-radius($radius) {
  -webkit-border-radius: $radius;
  -moz-border-radius: $radius;
  -ms-border-radius: $radius;
  border-radius: $radius;
}

.box {
  @include border-radius(10px);
}

SCSS - @Mixin@include로 기능 사용

컴파일

SCSS(SASS)는 웹에서 직접 동작 할 수 없습니다. 최종에는 표준 CSS로 동작해야하죠.
따라서 우리는 전처리기로 작성한 후 CSS로 컴파일 해줘야 합니다.

SassMeister

간단한 SCSS코드는 컴파일러를 설치하는게 부담될 수 있습니다.그럴 경우 SassMeister를 사용할 수 있습니다.

페이지 접속 후 바로 SASS나 SCSS 문법으로 코딩하면 CSS로 실시간 변환됩니다.
HTML을 작성하여 적용된 결과를 보거나 SASS 버전 설정 등 여러 환경 설정들을 지원하니 학습에 도움이 될 것입니다.

대표 컴파일러

다양한 방법으로 컴파일이 가능하지만 자바스크립트 개발 환경(Node.js)에서 추천하는 대표적인 컴파일러는 3가지가 있습니다.

  • node-sass
  • Gulp
  • Parcel

데이터 종류(Data Types)

SASS에서 사용하는 데이터 종류들의 특이사항

  • Numbers: 단위를 포함 하거나 포함하지 않음
  • Strings: 따옴표를 포함하거나 포함하지 않음
  • Nulls: 속성값으로 null이 사용되면 컴파일 하지 않음
  • Lists: ()를 붙이거나 붙이지 않음
  • Maps: ()를 꼭 붙여야 함
데이터 설명 예시
Numbers 숫자 1, .82, 20px, 2em…
Strings 문자 bold, relative, "/images/a.png", "dotum"
Colors 색상 표현 red, blue, #FFFF00, rgba(255,0,0,.5)
Booleans 논리 true, false
Nulls 아무것도 없음 null
Lists 공백이나 ,로 구분된 값의 목록 (apple, orange, banana), apple orange
Maps Lists와 유사하나 값이 key: Value 형태 (apple: a, orange: o, banana: b)

문법(Syntax)

주석(Comment)

CSS 주석은 /* ... */ 입니다. SCSS(SASS)는 JavaScript처럼 두 가지 스타일의 주석을 사용합니다.

SASS :

/* 컴파일되는
 * 여러 줄
 * 주석 */

// Error
/* 컴파일되는
* 여러 줄
    * 주석 */

Sass - 컴파일되는 여러 줄 주석을 사용할 때 각 줄 앞에 *을 붙여야 하고, *의 라인을 맞춰줘야 합니다.

SCSS :

// 컴파일되지 않는 주석
/* 컴파일되는 주석 */

SCSS - 각 줄에 *이 없어도 문제되지 않습니다. 따라서 기존 CSS와 호환이 쉽습니다.

중첩(Nesting)

SCSS는 중첩 기능을 사용할 수 있습니다.
상위 선택자의 반복을 피하고 좀 더 편리하게 복잡한 구조를 작성할 수 있습니다.

SCSS :

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

Compiled to:

CSS :

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

상위 선택자 참조(Ampersand)

중첩 안에서 & 키워드는 상위(부모) 선택자를 참조하여 치환합니다.

SCSS :

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

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

Compiled to:

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;
  }
}

Compiled to:

CSS :

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

@at-root (중첩 벗어나기)

중첩에서 벗어나고 싶을 때 @at-root 키워드를 사용합니다.
중첩 안에서 생성하되 중첩 밖에서 사용해야하는 경우에 유용합니다.

SCSS :

.list {
  $w: 100px;
  $h: 50px;
  li {
    width: $w;
    height: $h;
  }
  @at-root .box {
    width: $w;
    height: $h;
  }
}

Compiled to:

CSS :

.list li {
  width: 100px;
  height: 50px;
}
.box {
  width: 100px;
  height: 50px;
}

아래 예제 처럼 .list 안에 있는 특정 변수를 범위 밖에서 사용할 수 없기 때문에, 위 예제 처럼 @at-root 키워드를 사용해야 합니다.(변수는 아래에서 설명합니다)

SCSS :

.list {
  $w: 100px;
  $h: 50px;
  li {
    width: $w;
    height: $h;
  }
}

// Error
.box {
  width: $w;
  height: $h;
}

중첩된 속성

font-, margin- 등과 같이 동일한 네임 스페이스를 가지는 속성들을 다음과 같이 사용할 수 있습니다.

SCSS :

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

Compiled to:

CSS :

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

변수(Variables)

반복적으로 사용되는 값을 변수로 지정할 수 있습니다.
변수 이름 앞에는 항상 $를 붙입니다.

$변수이름: 속성값;

SCSS :

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

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

Compiled to:

CSS :

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

변수 유효범위(Variable Scope)

변수는 사용 가능한 유효범위가 있습니다.
선언된 블록({}) 내에서만 유효범위를 가집니다.

변수 $color.box1의 블록 안에서 설정되었기 때문에, 블록 밖의 .box2에서는 사용할 수 없습니다.

SCSS :

.box1 {
  $color: #111;
  background: $color;
}
// Error
.box2 {
  background: $color;
}

변수 재 할당(Variable Reassignment)

다음과 같이 변수에 변수를 할당할 수 있습니다.

SCSS :

$red: #ff0000;
$blue: #0000ff;

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

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

Compiled to:

CSS :

.box {
  color: #0000ff;
  background: #ff0000;
}

!global (전역 설정)

!global 플래그를 사용하면 변수의 유효범위를 전역(Global)로 설정할 수 있습니다.

SCSS :

.box1 {
  $color: #111 !global;
  background: $color;
}
.box2 {
  background: $color;
}

Compiled to:

CSS :

.box1 {
  background: #111;
}
.box2 {
  background: #111;
}

대신 기존에 사용하던 같은 이름의 변수가 있을 경우 값이 덮어져 사용될 수 있습니다.

SCSS :

$color: #000;
.box1 {
  $color: #111 !global;
  background: $color;
}
.box2 {
  background: $color;
}
.box3 {
  $color: #222;
  background: $color;
}

Compiled to:

CSS :

.box1 {
  background: #111;
}
.box2 {
  background: #111;
}
.box3 {
  background: #222;
}

!default (초깃값 설정)

!default 플래그는 할당되지 않은 변수의 초깃값을 설정합니다.
즉, 할당되어있는 변수가 있다면 변수가 기존 할당 값을 사용합니다.

SCSS :

$color-primary: red;

.box {
  $color-primary: blue !default;
  background: $color-primary;
}

Compiled to:

CSS :

.box {
  background: red;
}

{} (문자 보간)

#{}를 이용해서 코드의 어디든지 변수 값을 넣을 수 있습니다.

SCSS :

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

Compiled to:

CSS :

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

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

가져오기(Import)

@import로 외부에서 가져온 Sass 파일은 모두 단일 CSS 출력 파일로 병합됩니다. 또한, 가져온 파일에 정의된 모든 변수 또는 Mixins 등을 주 파일에서 사용할 수 있습니다.

Sass @import는 기본적으로 Sass 파일을 가져오는데, CSS @import 규칙으로 컴파일되는 몇 가지 상황이 있습니다.

  • 파일 확장자가 .css일 때
  • 파일 이름이 http://로 시작하는 경우
  • url()이 붙었을 경우
  • 미디어쿼리가 있는 경우
  • 위의 경우 CSS @import 규칙대로 컴파일 됩니다.

SCSS :

@import "hello.css";
@import "http://hello.com/hello";
@import url(hello);
@import "hello" screen;

파일 분할(Partials)

파일 이름 앞에 _를 붙여(_header.scss와 같이) @import로 가져오면 컴파일 시 ~.css 파일로 컴파일하지 않습니다.

Sass-App
  # ...
  ├─scss
  │  ├─header.scss
  │  ├─side-menu.scss
  │  └─main.scss
  # ...

main.scss로 나머지 ~.scss 파일을 가져옵니다.

SCSS :

// main.scss
@import "header", "side-menu";

그리고 이 파일들을 css/디렉토리로 컴파일합니다. 컴파일 후 확인하면 아래와 같이 scss/에 있던 파일들이 css/안에 각 하나씩의 파일로 컴파일됩니다.

Sass-App
  # ...
  ├─css
  │  ├─header.css
  │  ├─side-menu.css
  │  └─main.css
  ├─scss
  │  ├─header.scss
  │  ├─side-menu.scss
  │  └─main.scss
  # ...

이번에는 가져올 파일 이름에 _를 붙이겠습니다. 메인 파일인 main.scss에서는 _를 사용하지 않습니다.

Sass-App
  # ...
  ├─scss
  │  ├─_header.scss
  │  ├─_side-menu.scss
  │  └─main.scss
  # ...
// main.scss
@import "header", "side-menu";

아래처럼 별도의 파일로 컴파일되지 않고 사용됩니다.

Sass-App
  # ...
  ├─css
  │  └─main.css  # main + header + side-menu
  ├─scss
  │  ├─header.scss
  │  ├─side-menu.scss
  │  └─main.scss
  # ...

Webpack이나 Parcel, Gulp 같은 일반적인 빌드툴에서는 Partials 기능을 사용할 필요 없이, 설정된 값에 따라 빌드됩니다.
하지만 되도록 _를 사용할 것을 권장합니다.

연산(Operations)

Sass는 기본적인 연산 기능을 지원합니다.
레이아웃 작업시 상황에 맞게 크기를 계산을 하거나 정해진 값을 나눠서 작성할 경우 유용합니다.
다음은 Sass에서 사용 가능한 연산자 종류 입니다.

산술 연산자:

종류 설명 주의사항
+ 더하기
- 빼기
* 곱하기 하나 이상의 값이 반드시 숫자(Number)
/ 나누기 오른쪽 값이 반드시 숫자(Number)
% 나머지

비교 연산자:

종류 설명
== 동등
!= 부등
< 대소 / 보다 작은
> 대소 / 보다 큰
<= 대소 및 동등 / 보다 작거나 같은
>= 대소 및 동등 / 보다 크거나 같은

논리(불린, Boolean) 연산자:

종류 설명
and 그리고
or 또는
not 부정

숫자(Numbers)

상대적 단위 연산

일반적으론 절댓값을 나타내는 px 단위로 연산을 합니다만, 상대적 단위(%, em, vw 등)의 연산의 경우 CSS calc()로 연산해야 합니다.

SCSS :

width: 50% - 20px; // 단위 모순 에러(Incompatible units error)
width: calc(50% - 20px); // 연산 가능

나누기 연산의 주의사항

CSS는 속성 값의 숫자를 분리하는 방법으로 /를 허용하기 때문에 /가 나누기 연산으로 사용되지 않을 수 있습니다. 예를 들어, font: 16px / 22px serif; 같은 경우 font-size: 16pxline-height: 22px의 속성값 분리를 위해서 /를 사용합니다. 아래 예제를 보면 나누기 연산자만 연산 되지 않고 그대로 컴파일됩니다.

SCSS :

div {
  width: 20px + 20px; // 더하기
  height: 40px - 10px; // 빼기
  font-size: 10px * 2; // 곱하기
  margin: 30px / 2; // 나누기
}

Compiled to:

CSS :

div {
  width: 40px; /* OK */
  height: 30px; /* OK */
  font-size: 20px; /* OK */
  margin: 30px / 2; /* ?? */
}

따라서 /를 나누기 연산 기능으로 사용하려면 다음과 같은 조건을 충족해야 합니다.

  • 값 또는 그 일부가 변수에 저장되거나 함수에 의해 반환되는 경우
  • 값이 ()로 묶여있는 경우
  • 값이 다른 산술 표현식의 일부로 사용되는 경우

SCSS :

div {
  $x: 100px;
  width: $x / 2; // 변수에 저장된 값을 나누기
  height: (100px / 2); // 괄호로 묶어서 나누기
  font-size: 10px + 12px / 3; // 더하기 연산과 같이 사용
}

Compiled to:

CSS :

div {
  width: 50px;
  height: 50px;
  font-size: 14px;
}

문자(Strings)

문자 연산에는 +가 사용됩니다.
문자 연산의 결과는 첫 번째 피연산자를 기준으로 합니다.
첫 번째 피연산자에 따옴표가 붙어있다면 연산 결과를 따옴표로 묶습니다.
반대로 첫 번째 피연산자에 따옴표가 붙어있지 않다면 연산 결과도 따옴표를 처리하지 않습니다.

SCSS :

div::after {
  content: "Hello " + World;
  flex-flow: row + "-reverse" + " " + wrap;
}

Compiled to:

CSS :

div::after {
  content: "Hello World";
  flex-flow: row-reverse wrap;
}

색상(Colors)

색상도 연산할 수 있습니다.

SCSS :

div {
  color: #123456 + #345678;
  // R: 12 + 34 = 46
  // G: 34 + 56 = 8a
  // B: 56 + 78 = ce
  background: rgba(50, 100, 150, 0.5) + rgba(10, 20, 30, 0.5);
  // R: 50 + 10 = 60
  // G: 100 + 20 = 120
  // B: 150 + 30 = 180
  // A: Alpha channels must be equal
}

Compiled to:

CSS :

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

RGBA에서 Alpha 값은 연산되지 않으며 서로 동일해야 다른 값의 연산이 가능합니다.
Alpha 값을 연산하기 위한 다음과 같은 색상 함수(Color Functions)를 사용할 수 있습니다.

opacify(), transparentize()

SCSS :

$color: rgba(10, 20, 30, 0.5);
div {
  color: opacify($color, 0.3); // 30% 더 불투명하게 / 0.5 + 0.3
  background-color: transparentize($color, 0.2); // 20% 더 투명하게 / 0.5 - 0.2
}

Compiled to:

CSS :

div {
  color: rgba(10, 20, 30, 0.8);
  background-color: rgba(10, 20, 30, 0.3);
}

논리(Boolean)

Sass의 @if 조건문에서 사용되는 논리(Boolean) 연산에는 ‘그리고’,’ 또는’, ‘부정’이 있습니다. 자바스크립트 문법에 익숙하다면 &&, ||, !와 같은 기능으로 생각하면 됩니다.

SCSS :

$width: 90px;
div {
  @if not($width > 100px) {
    height: 300px;
  }
}

Compiled to:

CSS :

div {
  height: 300px;
}

2-2에서는 재활용(Mixins), 확장(Extend), 함수(Functions)를 알아보겠습니다.


Written by @Soojin Kim

넥스트이노베이션의 기술, 문화, 뉴스, 행사 등 최신 소식 및 넥스트이노베이션이 겪은 다양한 경험을 공유합니다.