꾸준한 개발자

계속적인 성장을 추구하는 개발자입니다. 꾸준함을 추구합니다.

계속 쓰는 개발 노트

CSS

Sass에 대한 간략한 공부

gold_dragon 2020. 12. 8. 16:59

Sass란?

css의 한계와 단점을 보완해서 보다 가독성이 높고 코드의 재사용에 유리한 css를 생성하기 위한 css의 확장입니다.

 

css의 경우 문법이 쉽기 때문에 쉽다는 장점이 있지만, 프로젝트의 규모가 커지거나 수정이 많아질수록 쉽게 지저분해질 수 있고 유지보수도 어려워진다는 단점이 있습니다.

 

Sass를 사용하게 되면 변수를 사용할 수 있고, 조건문과 반복문도 사용할 수 있습니다. 또한 import를 통해서 작게 쪼개서 합칠 수 있고, Nesting을 통해 중복 없이 html 구조 그대로 css를 만들 수 있습니다. 그리고 Mixin이라는 기능이 있는데, 이는 함수와 유사합니다.

Sass 설치

브라우저는 Sass의 문법을 알지 못하기 때문에 Sass파일을 css파일로 트랜스 파일링해주어야 됩니다.

 

Sass는 2006년 Ruby로 처음 개발되었다가 C++로 포팅한 Libsass, node.js 환경에서 Libsass를 사용할 수 있는 node-sass 등 다양한 포팅 버전이 등장했습니다. Sass는 최근에 Dart Sass로 재 구현되었습니다. Libsass나 node-sass는 현재 유지 관리는 되고 있으나 폐지되었으므로 Dart Sass를 사용하도록 하겠습니다. (2020년 12월 09일)

 

터미널에 다음 명령어를 입력하여 Sass를 설치합니다.

npm install -g sass

 

설치 후 sass --version 명령어를 통해 버전을 확인할 수 있습니다.

sass 버전 확인

트랜스파일링

그 후 에디터를 열어 foo.scss 파일을 하나 만들어줍니다. 그리고 내용에 다음 코드를 넣어줍니다.

$site_max_width: 960px;
$font_color: #333;
$link_color: #00c;
$font_family: Arial, sans-serif;
$font_size: 16px;
$line_height: percentage(20px / $font_size);

body {
  color: $font_color;

  // Property Nesting
  font: {
    size: $font_size;
    family: $font_family;
  }

  line-height: $line_height;
}

#main {
  width: 100%;
  max-width: $site_max_width;
}

그 후 해당 파일 경로에서 sass foo.scss:foo.css 명령어를 통해서 scss 파일을 css로 트랜스파일링할 수 있습니다. 그러면 같은 경로에 foo.css 파일이 생긴 것을 확인할 수 있습니다.

 

만약 특정 디렉터리 내의 모든 scss 파일을 css 파일로 일괄 트랜스파일링해서 지정한 디렉터리에 저장하려면 다음과 같은 명령어를 입력해줍니다.

sass src/sass:dist/css

 

그리고 sass --watch src/scss:dist/css 명령어를 통해서 scss 파일이 변경된 후 저장될 때마다 자동적으로 컴파일링을 시킬 수 있습니다.

 

만약 저 명령어도 길고 오타 확률이 높다 생각되면 package.json의 script를 이용해서 alias 등록해서 사용할 수 있습니다.

alias 등록

npm run build:sass 명령어를 입력하면 트랜스파일링이 이루어지는 것을 확인할 수 있습니다.

 

트랜스파일링할 때 2가지 스타일 중 하나를 선택할 수 있습니다.

sass --style expanded src/sass:dist/css 명령어를 사용하면 표준적인 스타일의 css 파일이 생성됩니다. 다른 스타일로는 

sass --style compressed src/sass:dist/css 명령어가 있습니다. compressed 스타일 경우 빈 공간이 없는 압축된 스타일의 css 파일을 생성합니다.

데이터 타입

7가지 데이터 타입을 제공합니다.

  • 숫자형
  • 문자열 -> 따옴표를 사용하는 경우와 사용하지 않는 경우가 있습니다. 
  • color
  • boolean
  • null -> 프로퍼티 값이 null인 변수가 지정되면 해당 룰셋은 트랜스파일링되지 않습니다.
  • list -> 배열과 유사 / 공백으로 구분돼 있거나 콤마로 구분돼 있습니다.
  • map -> 객체와 유사 / map-get 함수를 사용해서 원하는 값을 추출할 수 있습니다.

변수

변수명은 $로 시작합니다. 그리고 콜론(:)을 써주고 값을 써줍니다.

$site_max_width: 960px;
$font_color: #333;
$link_color: #00c;
$font_family: Arial, sans-serif;
$font_size: 16px;
$line_height: percentage(20px / $font_size);

body {
  color: $font_color;

  // Property Nesting
  font: {
    size: $font_size;
    family: $font_family;
  }

  line-height: $line_height;
}

#main {
  width: 100%;
  max-width: $site_max_width;
}

변수에는 유효 범위가 존재합니다. 코드 블록 내에서 선언된 변수는 지역 변수가 됩니다. 그런데 만약에 코드 블록 내에서 선언한 변수를 전역 변수로 지정하는 방법은 뒤에 !global을 써주면 전역 변수가 됩니다.

연산자

숫자 연산자

연산자 설명
+ 덧셈
- 뺄셈
* 곱셈
/ 나눗셈
% 나머지
== 동등
!= 부등
$width: 100px;

#foo {
  width: $width + 10; // 110px
}

#bar {
  width: $width + 10in; // 1060px
}

foo를 보면 연산자의 왼쪽 값을 기준으로 단위가 설정되는 것을 확인할 수 있습니다. bar도 마찬가지입니다.

 

하지만 $width에 10em을 더하게 되면 에러가 발생합니다. Sass 연산은 대상을 변환하여 연산할 수 없는 경우 에러를 출력합니다. %, em, rem, vh, vw, vmin, vmax와 같이 상대적인 값을 Sass는 알지 못합니다. 상대적인 값의 결괏값은 브라우저만 알 수 있습니다.

 

그렇기 때문에 상대적인 값을 갖는 단위의 연산은 동일한 단위를 갖는 값과의 연산만이 유효합니다. 즉, 5% + 10%와 같이 동일한 단위만 연산이 가능합니다. CSS3의 calc함수를 사용하면 이러한 문제를 해결할 수 있습니다.

 

그리고 또 주의할 점이 /는 css에서는 나눗셈의 의미가 아니라 값을 구분하는 의미를 갖습니다. 그렇기 때문에 Sass의 /연산자를 사용하기 위해서는 조건이 필요합니다.

  • 변수에 대해 사용
  • 괄호 내에서 사용
  • 다른 연산의 일부로서 사용
$width: 1000px;

width: $width / 2;            
height: (500px / 2);          
margin-left: 5px + 8px / 2px; 

변수를 css의 /와 같이 사용하고 싶을 때는 #{}(Interpolation)를 사용합니다.

p {
  $font-size: 12px;
  $line-height: 30px;
  font: #{$font-size}/#{$line-height};  // 12px/30px
}

컬러 연산자

모든 산술 연산자는 컬러값에도 사용할 수 있습니다.

p {
  color: #010203 + #040506;
  // R: 01 + 04 = 05
  // G: 02 + 05 = 07
  // B: 03 + 06 = 09
  // => #050709
}

p {
  color: #010203 * 2;
  // R: 01 * 2 = 02
  // G: 02 * 2 = 04
  // B: 03 * 2 = 06
  // => #020406
}

p {
  color: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75);
  // alpha(투명도)는 연산되지 않음
  // color: rgba(255, 255, 0, 0.75);
}

문자열 연산자

+ 연산자는 자바스크립트와 같이 문자열을 연결할 수 있습니다. 만약 따옴표가 있는 문자열과 없는 문자열을 연결하려고 할 경우 좌항의 문자열을 기준으로 따옴표를 처리합니다.

불린 연산자

연산자 설명
&& and
|| or
! not

Nesting

Sass의 유용한 확장 기능으로 선언을 중첩하는 것입니다. css는 후손 셀렉터의 경우 부모 요소를 기술해야 합니다. 하지만 sass의 nesting을 사용하면 후손 셀렉터를 간단히 기술할 수 있습니다. HTML의 구조로 코드를 짜기 때문에 가독성이 좋아집니다.

 

nesting은 프로퍼티에도 사용할 수 있습니다.

Ampersand(&)

&는 부모요소를 참조하는 셀렉터입니다.

a {
  color: #ccc;

  &.home {
    color: #f0f;
  }

  &:hover {
    text-decoration: none;
  }

  // & > span (X)
  > span {
    color: blue;
  }

  span {
    color: red;
  }
}

!default

!default flag는 할당되지 않은 변수의 초기값을 설정합니다. 이미 값이 할당되어 있는 변수에는 적용되지 않습니다.

$content: null;
$content: "Non-null content" !default;

#main {
  content: $content; // "Non-null content"
}

위 개념은 partial에 매우 유용합니다.

@import

1개의 css 파일에 모든 스타일을 기술하면 유지 보수하기 힘들고 가독성이 좋지 않다. 기능에 따라 css 파일을 분리하면 재사용 및 유지보수 측면에서 유리합니다.

 

Sass는 @import directive를 사용해서 분리된 stylesheet 파일을 import 할 수 있습니다. 기존의 css의 @import보다 편리한 기능을 제공합니다. 확장자를 생략할 수 있고, 여러 개의 파일을 한 번에 임포트 할 수 있습니다. 그리고 변수를 사용해 문자열을 생성해서 임포트할 수도 있습니다.

 

여러 개의 파일로 분할하는 것 또는 분할된 파일을 partial이라 합니다. partial 된 Sass 파일명의 선두에는 _(underscore)를 붙입니다.

if()

bilt-in if() 함수는 주어진 조건을 판단하여 결과를 리턴합니다.

if(condition, if_true, ir_false)

@if...@else

@if...@else를 사용하면 조건 분기가 가능합니다.

$type: monster;

p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}

@for

@for을 이용해서 반복문을 사용할 수 있습니다.

@for $i from 1 through 3 {
  .item-#{$i} { width: 2em * $i; }
}

@each

@each와 list 또는 map의 요소에 대해 반복을 실시합니다.

// List
@each $animal in puma, sea-slug, egret, salamander {

  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
  }
}

// Map
// $header: h1, $size: 2em
// $header: h2, $size: 1.5em
// $header: h3, $size: 1.2em
@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) {
  #{$header} {
    font-size: $size;
  }
}

@while

$i: 6;
@while $i > 0 {
  .item-#{$i} { width: 2em * $i; }
  $i: $i - 2;
}

Mixin

중복 기술을 방지하기 위해 빈도가 높은 마크업을 사전에 정의해서 필요할 때에 불러 사용하는 방법입니다.

// 지름이 50px인 원
@mixin circle {
  width: 50px;
  height: 50px;
  border-radius: 50%;
}

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

  background: #f00;
}

매개변수를 사용할 수 있습니다. 매개변수에 기본값도 정할 수 있습니다.

@mixin circle($size) {
  width: $size;
  height: $size * 2;
  border-radius: 50%;
}

.box {
  @include circle(100px);

  background: #f00;
}

※ 참조 -> 강사 이웅모, Sass 강의

'CSS' 카테고리의 다른 글

word-break와 word-wrap  (0) 2020.09.11
margin collapse 관련 레퍼런스 해석 (마진 병합)  (0) 2020.09.01
<strong>과 <em> 차이점  (0) 2020.07.30
CSS 속성 선택자  (0) 2020.07.30
IR 기법 - 대체 텍스트 숨김  (0) 2020.07.24