Blog/CSS

[아무튼 Sass] 2. 기본 작성법 익히기 - 중첩, 참조, 변수, 보간

나나 (nykim) 2022. 4. 5. 21:15
320x100

 

 

 

프롤로그

 

 

[아무튼 Sass] 1. 시작하기의 다음 글입니다. 두 번째 글이지만 어느덧 반년만... 😉💦

 

이런 분들을 위한 글입니다.

 - CSS를 다룰 수 있어요

 - 하지만 Sass는 1도 몰라요

 

 

아무튼 Sass 시리즈
1. 시작하기 - Sass 개념, 컴파일러 설치
2. 기본 작성법 익히기 - 중첩, 참조, 변수, 보간 👈 Here!
3. 더 편하게 CSS 다루기 - mixin, extend, 모듈화(import/use)

4. 더 멋지게 활용하기 - 흐름제어, 내장 모듈, 함수
이번 글에서 다루는 것:
- 중첩, 부모참조 선택자
- 변수, 보간
- 인라인 주석
- 출력스타일 설정

 

 


 

 

1) 중첩: 이것이 "C"SS

 

지난 글에서는 Sass 만 설치하고 똑 끝나버려서 '왜 굳이 이걸 설치해서 써야하지 🤔' 하는 생각이 들 수도 있는데,

아무튼 Sass는 쓰기 편하니까 믿어주세요(?)

 

Sass가 제공하는 어썸한 문법들을 몇 가지 알아볼 건데, 그 중 하나는 CSS를 중첩해서 사용하는 점입니다.

 

 

CSS의 뜻은? 케스케이딩 스타일 시트죠! 

넵. CSS의 가장 큰 특징은 "C", 바로 케스케이딩*에 있습니다.
*cascading: 위에서 아래로 흐르는

 

그래서 CSS는 .grand-parent > .parent > .child와 같이 부모에서 자식 순서로 작성합니다.

요소의 스타일은 상속을 통해 적용되고요.

엉뚱한 애한테 스타일이 상속되지 않도록 케스케이딩을 관리하는 게 CSS 작성의 중요 포인트죠.

 

 

하지만 CSS의 길고 길고 기다란 셀렉팅에선 cascading 의 느낌을 받을 수가 없는데요...

 

이건 흐른다기 보단 기어가는 거...?

 

하지만 이걸 Sass 문법으로 작성한다면?!

 

A-ha!

 

계층 구조가 시각적으로 바뀌면서 한눈에 들어옵니다. 

이제야 "Cascading" 이란 느낌이네요! 부모 선택자를 반복하지 않아도 되니 보기에도 훨씬 좋습니다.

 

 

설명은... 이게 끝이에요! 😋

어떻게 사용해야 할지 감이 오실 텐데, 중첩하고 싶은 만큼 대괄호{} 안에 자식 셀렉터를 넣으면 됩니다.

이렇게 중첩해서 쓰면 좋은 점은 어디서부터 어디까지가 셀렉터인지 한눈에 알 수 있다는 점입니다.

 

.wrap {
  //...
  .main {
    //...
    .section {
       //...
       .article {
         //...
         .title {
           //...
         }
       }
    }
  }
}

 

하지만 얼마나 중첩해서 쓸 것인가는 고민이 필요한 부분입니다.

저는 너무 들여쓰는 경우 '그래서 얘 부모가 누구지...' 하고 한눈에 파악이 힘들 때가 있더라고요.

BEM 방법론을 사용한다면 Element 단위에서 끊어 쓰거나, CSS Module 을 사용한다면 어차피 중복되지 않을 테니 깊게 들여쓰지 않아도 되긴 하겠죠!

 

 


 

 

2) 부모참조: 이름을 물려받는 중입니다

 

Sass에는 특별한 선택자가 몇 개 있는데, 그 중 하나인 & 를 소개합니다. 

이 &는 중첩된 상태일 때 외부의 선택자를 참조할 수 있습니다.

 

 

 

 

짠, 부모선택자의 이름을 반복해서 쓸 필요없이 & 하나만으로 뚝딱 대체할 수 있습니다. 

특히 부모선택자의 이름을 계속해서 가져다 쓰는 BEM 방법론에 찰떡이죠.

 

.accordion {
  max-width: 600px;
  margin: 4rem auto;
  width: 90%;
  font-family: "Raleway", sans-serif;
  background: #f4f4f4;

  &__copy {
    display: none;
    padding: 1rem 1.5rem 2rem 1.5rem;
    color: gray;
    line-height: 1.6;
    font-size: 14px;
    font-weight: 500;

    &--open {
      display: block;
    }
  }
}

 

컴파일된 결과와 비교해 보세요!

 

 

 

이는 자기 자신을 재선택할 때도 유용합니다. &:hover& + p 처럼 스스로를 선택해서 작성할 수도 있죠.

 

button {
  color: blue;

  &:hover {
    opacity: 0.5
  }

  &:disabled {
    opacity: 0.3;
    cursor: not-allowed;
  }

  &.isLoading {
    color: green;
  }

  & + button {
    margin-top: 10px;
  }
};

 

 

 

&가 컴파일되면서 부모 선택자로 치환되는 것이므로, & span / &span / &.span 은 각각 다르게 취급됩니다.

그럼 아래의 Sass 문이 어떻게 컴파일될지 느낌이 팍 오죠!

 

.hello {
  & span {
    color: blue;
  }

  &span {
    color: green;
  }

  &.span {
    color: purple;
  }
}

 

 

답은 차례대로 ① .hello span ② .hellospan ③ .hello.span 입니다

SassMeister 에서 쳐보시면 금방 감이 잡힐 거예요 🤩

 

 

유의할 점 한 가지! & 선택자는 복합 선택자의 시작 부분에만 쓸 수 있습니다.

예를 들어 :not(&) 는 가능하지만 .item& 처럼 끝에 쓰는 건 불가능합니다.

 

Error: "&" may only used at the beginning of a compound selector

 

 

또, @media 같은 at-rules 가 중첩되어 있으면 스타일 규칙이 그 안에 있도록 바꿔주기 때문에 쉽게 조건을 추가할 수 있어요.

 

 

 


 

 

3) 변수: 걔가 얘야

 

Sass에서는 $변수명: 값; 으로 변수를 선언해 사용할 수 있습니다. 

우리가 지난 글에서 예제로 살펴봤던 것처럼 쓰면 됩니다. 

변수에는 문자, 숫자, 불린, 컬러값, null 등 정말 다양한 값을 담을 수 있어요!

 

$width: 100rem;
$font: "Noto Sans KR";
$color: #000;
$darkMode: true;
$init: null;
TMI
이렇게 속성이나 변수 선언 오른쪽에 있는 값을 SassScript 라고 부릅니다.
값을 담는 데서 끝이 아니고 != 처럼 비교하거나 +/-/* 등의 산술을 할 수도 있고, 함수의 인자로 넘길 수도 있죠.
자세한 활용법은 투비 컨티뉴 🙌

 

 

또한 선언 위치에 따라 전역변수 또는 지역변수로 사용할 수도 있어요.

 

.header {
  $var-header: '이 변수는 .header 내에서만 쓸 수 있어요!';
}

.body {
  content: $var-header; //오류!
}

 

Error: Undefined variable.

 

 

물론 CSS에서도 var(--변수명) 이라고 글로벌 변수를 쓸 수 있어요!

하지만 Sass의 변수는 CSS 변수와 조금 다릅니다.

  • Sass의 변수는 컴파일되면서 사라집니다. CSS 파일에 보이지 않아요.
  • Sass의 변수는 한 번에 단 하나의 값만 가집니다.
  • Sass의 변수는 재할당 시 이전의 내용을 바꾸지 않습니다.

 

$var: 'nana'; 
.first { content:$var; } //nana
$var: 'like'; 
.second { content:$var; } //like

 

 

또, Sass 변수에서 하이픈(-)과 언더스코어(_)는 동일하게 취급됩니다.

따라서 $font-size와 $font_size는 완벽하게 동일합니다! 🤟

 

$font_size: 10px;
$font-size: 200px;

.underscore {
    font-size: $font_size; //200px;
}

.hypen {
    font-size: $font-size; //200px;
}
TMI
옛날에는 Sass 변수에 언더스코어만 쓸 수 있었으나 업데이트되면서 하이픈도 지원하게 됐다고 하네요!
마이그레이션을 쉽게 하기 위해서 둘을 같은 걸로 취급하는 모양입니다.

 

 

그렇다면 변수는 언제 쓰는 게 좋을까요? 그건 쓰는 사람 마음대로! ...긴 한데요,

변수가 난잡하면 그것 나름대로 보기 어려워져서 '쓸 만한 상황이다'라고 판단될 때 쓰는 게 좋겠죠.

  • 값이 여러 곳에서 반복되거나
  • 수정될 가능성이 높을 때 사용하는 것이 가장 좋겠습니다.

 

 


 

 

4) 보간: 슬쩍 끼워넣기!

 

변수를 font-size: $size;와 같이 불러다 쓸 수 있다는 걸 배웠습니다. 

그렇다면 CSS 속성값 안에 그대로 끼워넣는 것도 가능할까요?

 

$name: "cart";
.icon-cart {
    background-image: url("/icons/$name.png");
}

/*
 출력결과:
 .icon-cart {
   background-image: url("/icons/$name.png");
 }
*/

 

의도한 거랑은 다르게 나왔네요. 저 이미지 주소 내에 $name을 끼워넣고 싶었는데 말이죠.. 머쓱...

 

아니면 이런 것도 가능할까요? position 을 변수로 주고 top: 50px 을 적용하고 싶습니다.

 

$position: top;
.header {
    position: fixed;
    $position: 50px;
}

/*
 출력결과: 
 .header {
   position: fixed;
 }
 (내 $position 어디 간 거야... 😿)
 */

 

 

넵, 문자열이나 셀렉터 등에 변수를 쓰려면 그냥은 안 되고 #{} 라는 보간(Interpolation)이 필요합니다.

방법은 변수를 #{} 로 감싸주기만 하면 됩니다!

 

$position: top;
$name: cart;
$height: 200px;

.header {
    position: fixed;
    #{$position}: 50px;
    background-image: url("/icons/#{$name}.png");
    width: calc(100vh - #{$height});
}

/*
 출력결과:
 .header {
   position: fixed;
   top: 50px; //야호 top을 인식했다!
   background-image: url("/icons/cart.png"); //야호(2) cart를 인식했다!
   width: calc(100vh - 200px);
 }
*/

 

만약 CSS 변수에서 Sass 변수나 함수를 끌어다쓰고 싶다면 보간법을 사용합니다.

 

$color-accent: #0080ff;

:root {
  --color-accent: #{$color-accent};
  --color-accent-100: #{rgba($color-accent, 0.07)};
  --color-accent-200: #{rgba($color-accent, 0.2)};
  --color-accent-300: #{rgba($color-accent, 0.4)};
}

 

 

 

한 가지 짚고 넘어가면 좋은 점! 보간이 리턴하는 것은 따옴표가 없는 문자열(unquoted strings)입니다. 

따라서 단위 사이에 끼워넣을 때는 보간을 쓰기보다는 아래와 같이 쓰는 걸 추천합니다.

 

$size: 100;

.main {
    width: #{$size}rem; //Not recommend 😐
}

.footer {
    width: #{$size} * 1rem; //Good 😊
}

 

이유는 변수에 단위가 잘못 들어갔을 때, 컴파일 과정에서 에러를 잡을 수 없기 때문입니다.

 

$size: 100px; //어이쿠! 모르고 px을 써버렸다!

.main {
    width: #{$size}rem;
}

.footer {
    width: #{$size} * 1rem;
}

/*
 컴파일 결과:
 .main { width: 100pxrem; }
 .footer { //에러 }
*/

 

보간은 문자열을 리턴하므로 pxrem이란 요상한 단위가 튀어나오게 됩니다.
컴파일러 입장에선 문자열끼리 잘 있는 것이므로 딱히 에러를 내뱉지 않습니다. (다행히 브라우저는 이 단위를 무시하겠지만요)

하지만 100px * 1rem은 명확하게 단위가 맞지 않으니 개발단계에서 에러를 캐치하고 수정하는 것이 가능합니다.

 

 

또, 문자열을 감싼 따옴표는 보간으로 사용 시 컴파일 과정에서 사라집니다. 

 

$var: "Nana";

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

/*
 출력결과:
 .hello {
   background-image: url("/images/Nana.png");
 }
*/

 

 

 


 

 

5) 인라인 주석: 우리끼리만 보는 주석

 

CSS에서 주석은 /* */형태로 사용했죠.

 

CSS 파일은 누구나 뜯어볼 수 있기 때문에 비밀스러운(?) 주석을 다는 것이 불가능합니다.

개발하다보면 개발에만 필요한 주석을 달아야할 때가 있는데 말이죠. 

이런 불편함을 해소하고자 Sass에서는 //형태로 인라인 주석을 사용할 수 있습니다. 

인라인 주석은 어디든 끼워넣을 수 있고, 컴파일 과정에서 뿅 사라집니다.

 

 

 

 


 

 

6) 출력스타일: 어떤 스타일로 해드릴까요

 

Dart Sass는 두 가지의 출력 스타일을 제공합니다.

  1. expanded = 펼쳐주세요! (기본값)
  2. compressed = 압축해주세요!

 

compressed 옵션을 택하면 빈 여백을 가능한 제거하고 전체 스타일시트를 한 줄에 작성해 줍니다.

 

저번 글에서 플래그로 --watch 옵션을 껴넣었던 것처럼, --style 옵션으로 출력 스타일을 제어할 수 있습니다.

터미널에서 sass 명령을 내릴 때 아래와 같이 입력해 보세요.

sass --style=compressed style.scss style.css

 

그럼 이렇게 꽉꽉 압축시킨 CSS 파일을 얻을 수 있습니다! 알아서 압축도 해주고 좋네요 😉

 

 

compressed 옵션일 때는 일반 CSS 주석 /* 주석 */ 도 제거됩니다.

하지만 ! 를 붙여 강조하면 압축모드에서도 표시되므로, 중요한 정보는 /*! 중요한 주석 */ 형태로 남길 수 있습니다.

 

 


 

 

에필로그

 

CSS 작성을 좀 더 편하게 해줄 몇 가지 Sass 문법에 대해 알아봤습니다. 역시 편한 게 최고쥬

다음 글은 mixin, extend, 모듈화처럼 쪼개서 여기저기 가져다쓰는 법에 대해 써보려고 합니다.

 

글 마무리가 제일 어렵네요... 아무튼 긴 스크롤 함께해주셔서 감사합니다 🤗

 

 

728x90