SASS(SCSS) 반복적인 CSS는 그만 - SASS 한방에 끝내기 (변수, 중첩, 믹스인)

2023. 8. 10. 00:19HTML,CSS

728x90

이번 포스트 시리즈에서는 SASS에 대해서 알아보는 시간을 가져보겠습니다.

사실 CSS를 잘 알고 있다면 SASS를 사용하고 익숙해지는데 큰 어려움을 느낄 사람은 없다고 생각합니다.

그 이유는 SASS는 퍼블리셔/개발자들이 CSS를 더 쉽고 반복 없이 효율적으로 사용할 수 있게 만든 것이기 때문입니다.

 

SASS는 전처리기이기 때문에 결국에 최종 결과물은 네이티브 CSS형태로 바뀌지만, SASS (Syntactically Awesome Style Sheets)가 제공하는 탁월한(?) 문법을 사용하면 개발자들이 가장 싫어하는 반복적이고 귀찮은 일들을 많이 줄일 수 있게 됩니다.

 

 

전처리기 SASS(SCSS)

 

SASS의 장점

앞서 언급했지만 SASS의 가장 장점은 효율성에 있습니다.

SASS가 어떻게 효율적인 코드를 작성할 수 있도록 해주는지는 Chat GPT를 참고해보도록 하겠습니다.

 

 

요약해 보자면 아래와 같습니다.

 

- Modularity & Reusability  - 모듈화와 재사용성

- Nesting - 중첩

- Variables - 변수

- Mixins - 믹스인 (재사용가능한 스타일 블록)

- Functions - 함수

- Imports and Partials - 코드 분리를 가능하게 하는 구문들

- Extensibility - 확장성

- Advanced CSS Features - 그 외 CSS에서 제공하지 않는 추가 기능들

 

뭔가 거창해보이지만 하나하나 살펴보면 그리 어렵지 않은 개념들로

개발자라면 이미 한번쯤은 접해본 개념들이기 때문에 시작하기도 전에 겁먹지 않으시길 바랍니다.

 

위 목록중 이번 기초 편에서 다룰 내용들은 아래와 같습니다

1. 변수  (Variables)
2. 중첩 (Nesting)
3. 믹스인 (Mixins)

 

 


 

잠깐, SASS와 SCSS의 차이점?

시작하기 앞서 헷갈릴 수 있는 SASS와 SCSS에 대해 설명을 하고 넘어가 보도록 하겠습니다.

SASS는 크게 두 가지 문법(확장자)이 있는데 그 두 가지가 SASS(Syntactically Awesome Style Sheets)와 SCSS(Sassy CSS)입니다.

 

기본 SASS 문법은 CSS 형태와 좀 다르기 때문에 러닝커브가 존재합니다. 기존 CSS와 달리 콜론이나 괄호등 생략된 부분이 많아 처음 접하시는 분들은 익숙해지는데 시간이 걸릴 수가 있다는 단점이 있습니다. 그렇다고 기본 CSS 문법을 인식하지도 않으니 무조건 SASS 문법을 숙지하고 사용해야 합니다.

 

추후에 이러한 부분을 보완하고자 공개된 게 SCSS 문법입니다. SCSS는 CSS의 슈퍼셋(superset)이기 때문에 CSS 문법 그대로 사용해도 잘 적용이 되고 문법 또한 CSS와 크게 다르지 않아 러닝커브가 낮습니다. 필자 또한 이러한 이유 때문에 SCSS를 사용하기 시작했고 처음엔 중첩 기능만 사용하다가 점차 효율적이고 유지보수가 용이한 코드 작성을 위해 SASS가 제공하는 기능들을 추가적으로 배우면서 사용할 수 있었습니다.

 

물론 무조건 SCSS가 더 좋은 선택이라고 할 순 없지만, SASS 입문용으로는 SCSS 문법이 더 적합하다고 생각되기 때문에  해당 포스트에서 언급되거나 작성되는 코드들은 전부 기본 SASS문법이 아닌 SCSS로 작성할 예정입니다.

 

sass , scss , css

 


1. 변수 (Variables)

자주 반복하여 사용하는 값들은 변수로 지정해 필요할 때마다 불러서 사용할 수 있습니다.  요즘에는 CSS에 스펙에 사용자 속성(custom properties)이 추가되어 변수를 지정해 사용할 수 있지만 예전에는 SASS가 제공하는 큰 이 점 중 하나였습니다.

 

변수 선언

$변수명: 값
/* $변수명: 값; */

/*예시*/
$max-screen-width: 1200px;
$theme-color: #34a753;

.home {
  max-width: $max-screen-width;
  background-color: $theme-color;
}

 

위와 같이 반복적으로 사용할만한 값들 (최대 너비나 테마색값등)을 지정해 둔 뒤 사용할 수 있습니다.

해당 변수는  셀렉터 안이 아닌 밖에 선언을 했기 때문에 해당 파일에 작성된 모든 셀렉터 안에서 사용할수 있습니다.

변수들을 파일별로 분리해서 사용하는 방법은 Imports and Partials 부분에서  다루어보도록 하겠습니다.

 

변수의 유효범위 (Scope)

만약 변수의 유효범위를. home 셀렉터로 하고 싶다면 변수 선언을 아래와 같이. home 셀렉터 내부에서 해주면 됩니다.

.home {
  $max-screen-width: 1200px;
  $theme-color: #34a753;
  max-width: $max-screen-width;
  background-color: $theme-color;
}

.article {
  color: $theme-color; /* Undefined variable $theme-color 컴파일 에러 */
}

 

보간법 (Interpolation)

만약 변수값을 속성값이 아닌 속성명으로 사용할 때는 어떡해야 할지 알아보도록 합시다.

$radius: "border-radius";

.border {
   border: 1px solid black;
   $radius: 5px;   /* x 컴파일 에러 */
   #{$radius}: 5px;  /* o border-radius: 5px */
}

 

사실 보간법은 많은 프로그래밍 언어에서 사용 중인 개념이라 깊게 설명하진 않고 좀 더 실용적인 예시를 한번 들어 보겠습니다.

 

@for $i from 1 through 5 {
  .color#{$i} {
    background-color: lighten(red, 10% * $i);
  }
}

/* 컴파일 결과
.color1 {
  background-color: #f33;
}
.color2 {
  background-color: #f66;
}
.color3 {
  background-color: #f99;
}
.color4 {
  background-color: #fcc;
}
.color5 {
  background-color: white;
}
*/

 

 

아직 @for를 배우지 않았지만 충분히 예상이 가능한 코드입니다.

해당 코드를 컴파일하면 아래와 같이 .color1 부터 .color5까지 총 5개의 셀렉터 작성한 거와 같은 효과를 낼 수 있습니다.

 

 

2. 중첩 (Nesting)

필자가 SASS를 사용하게 된 이유 중 하나로 간단하지만 강력한 기능입니다. 조금 규모 있는 프로젝트를 진행하게 되면 코드의 양이 많아짐에 따라 특정 요소를 선택하여 스타일을 제대로 적용하기 힘들어지기 마련입니다. 그러다 보면 하나둘씩 !important를.. 그러나 중첩기능을 제공하는 SASS를 사용하게 되면 종속관계가 더 명확해짐에 따라 적용 우선순위도 눈에 쉽게 보이기 때문에 유지보수가 용이합니다. 

 

💡 최근에는 네이티브 CSS에서도 일부 브라우저를 제외하고 중첩이 가능하긴 하지만 이번 포스트는 SASS에 관련된 포스트이기 때문에 넘어가도록 하겠습니다.

 

일반적인 내비게이션바를 예로 들어 보겠습니다.

 

HTML

  <nav class="navbar">
    <a href="#">Home</a>
    <a href="#">About</a>
    <a href="#" class="submenu-trigger">Services</a>
    <ul class="submenu">
      <li><a href="#">Service 1</a></li>
      <li><a href="#">Service 2</a></li>
      <li><a href="#">Service 3</a></li>
    </ul>
    <a href="#">Contact</a>
  </nav>

네이티브 CSS

.navbar {
  background-color: #333;
  color: #fff;
  padding: 10px;
}

.navbar a {
  color: #fff;
  text-decoration: none;
  padding: 5px 10px;
}

.navbar a:hover {
  background-color: #555;
}

.submenu {
  display: none;
}

.submenu-trigger:hover + .submenu {
  display: block;
  position: absolute;
  top: 100%;
  left: 0;
  background-color: #555;
}

.submenu a {
  display: block;
  padding: 5px 10px;
  color: #fff;
  text-decoration: none;
}

.submenu a:hover {
  background-color: #777;
}

SCSS

.navbar {
  background-color: #333;
  color: #fff;
  padding: 10px;
  
  a {
    color: #fff;
    text-decoration: none;
    padding: 5px 10px;

    &:hover {
      background-color: #555;
    }
  }

  .submenu {
    display: none;

    &:hover {
      display: block;
      position: absolute;
      top: 100%;
      left: 0;
      background-color: #555;
      
      a {
        display: block;
        padding: 5px 10px;
        color: #fff;
        text-decoration: none;

        &:hover {
          background-color: #777;
        }
      }
    }
  }
}

 

보시는 거와 같이 SCSS를 사용할 경우, 더 길어질 수는 있으나 훨씬 읽기 쉽고 마크업을 보지 않더라도 navbar안에 submenu라는 클래스가 속해있다는 종속관계를 한눈에 알아볼 수 있습니다.

 

부모 셀렉터 참조  (&)

위에 예제로 이미 눈치채셨을 수도 있지만 SCSS에서는 연산자 &를 통해 부모 셀렉터를 쉽게 참조할 수 있습니다. 

 

/*CSS*/

a {
 /* 앵커 태그 스타일 */
}

a:hover{
 /* 앵커 태그 호버시 스타일 */
}


/*SCSS*/

a {
 /* 앵커 태그 스타일 */
  &:hover {
 /* 앵커 태그 호버시 스타일 */
  }
}

 

위 예제에서는 hover를 예시로 들었지만 다른 가상요소, 클래스 (::before, ::after, nth-child()) 전부 같은 방법으로 사용가능합니다.

 

속성 중첩

CSS에서 속기(Shorthand)로 작성가능한 속성값들을 아래와 같이 중첩으로 사용가능합니다. (예: background, border, font, margin, padding)

 

/* css */

.hero {
    background-color: transparent;
    background-image: none;
    background-repeat: repeat;
    background-position: top left;
    background-attachment: scroll;
}

/* scss */

.hero {
   background {
    color: transparent;
    image: none;
    repeat: no-repeat;
    position: top left;
    attachment: scroll;
    }
}

 

중첩 해체 (@at-root)

많이 쓰이지는 않지만 중첩을 해체하고 싶을 때에는 at-rules 중 하나인 @at-root 사용할 수 있습니다

💡 SASS에서는 @(at)가 붙은 규칙(at-rules)들을 여러 개 사용합니다. @mixin / @include/ @each 등..
/* SCSS */
.section{
    background-color: white;
    @at-root .content {
        background-color: black;
    }
}

/* 컴파일 결과
.section{
    background-color: white;
}
.content
    background-color: black;
}
*/

 

@at-root를 사용하지 않았다면

 .section .content { background-color: black }

위와 같이 컴파일되어야 하겠지만 at-root 규칙을 통해 중첩을 해체하였기 때문에 .content는 .section에 종속되지 않게 됩니다.

 

 

3. 믹스인 (Mixin)

SASS가 반복을 없애고 효율적으로 코드를 작성할 수 있게 도와주는데 큰 역할을 하는 게 바로 이 믹스인입니다.

CSS를 사용하다 보면 특히 반복적으로 많이 사용하는 코드가 있는데 이 같은 반복적인 코드를 재사용하기 위해 틀을 짜놓고 해당 틀을 반복적으로 사용하는 개념입니다.

 

해당 개념도 마찬가지로 SASS의 고유개념은 아니기 때문에 깊게 들어가진 않고, 어떤 식으로 믹스인을 선언하고 사용하는지에 중점을 두도록 하겠습니다.

 

중첩해체 부분에서 잠시 언급한 at 규칙을 통해 믹스인을 정의하고 사용할 수 있습니다.

 

@mixin [믹스인 이름] - 정의
@include [믹스인 이름] - 사용

 

믹스인으로 지정하여 사용할 수 있는 건 너무 많지만 일단 현업에서 많이 사용하는 flex를 예시를 한번 들어보도록 하겠습니다. 

아래는 중앙정렬을 위해 자주 사용되는 flexbox의 속성명과 값입니다.

 

.box {
    display: flex;
    justify-content: center;
    align-items: center;
}

 

비록 많은 양의 코드는 아니지만 여러 곳에서 자주 쓰이는 만큼 믹스인으로 선언하기 적합합니다. 

 

믹스인 선언 (@mixin)

@mixin flex-center {
    display: flex;
    justify-content: center;
    align-items: center;
}

 

믹스인 사용 (@include)

.box {
 @include flex-center;
}

.box1 {
 @include flex-center;
}

 

중앙 정렬이 아니고 justify-content: space-between을 사용하고 싶다면 물론 새로운 믹스인을 만들어서 사용하면 됩니다.

 

@mixin flex-space-between {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

 

하지만 저희는 개발자이기 때문에 더 효율적인 방법은 없을까라는 생각을 합니다. 그래서 믹스인에 인자를 전달하는 방법을 쓰게 됩니다.

 

믹스인 인자 

@mixin flex($justify, $align) {
    display: flex;
    justify-content: $justify;
    align-items: $align;
}
.box {
  @include flex(space-between, center);
}

 

함수에 인자를 전달하듯이 flex라는 믹스인에 justify라는 가로 측 인자와 align이라는 세로 측 인자를 설정해 줄 수 있습니다.

이제 flex라는 믹스인은 더 이상 중앙 정렬용 믹스인이 아닌 사용자가 지정하는 값에 따라 정렬방법이 바뀌는 범용성 높은 믹스인으로 사용할 수 있습니다.

 

믹스인 인자 기본값 설정 (:)

자주 사용하는 값으로 기본 인자값을 설정해 줄 수도 있습니다. flex는 중앙 정렬로 가장 많이 쓰이기 때문에 필자는 아래와 같이 기본값을 center로 지정해 두고 믹스인 호출 시 인수값을 생략하여 사용합니다.

@mixin flex($justify: center, $align: center) {
    display: flex;
    justify-content: $justify;
    align-items: $align;
}
.box {
  @include flex;
}

/*	컴파일 결과
.box {
   display: flex;
   justify-content: center;
   align-items: center;
}
 */

 

 

믹스인에 내용 추가하기 (@content)

믹스인에 사용자가 추가적으로 스타일을 작성할 수 있도록 하기 위해서 @content 규칙을 사용할 수 있습니다.

만약 위에서 정의한 flex 믹스인에 flex-flow 속성값을 변경하고 싶다고 했을 때 어떤 방법으로 가능한지 살펴보겠습니다.

 

@mixin flex($justify: center, $align: center) {
    display: flex;
    justify-content: $justify;
    align-items: $align;
    @content;
}
.box {
 @include flex {
   flex-flow: column wrap;
 }
}

/* 컴파일 결과
.box {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-flow: column wrap;
}
*/

 

사실 위 예제에서는 @content 없이 .box 셀렉터안에 flex-flow: column wrap을 적용해도 같은 결괏값을 초래하기 때문에 해당 용도보다는 아래와 같이 미디어 쿼리를 믹스인으로 지정하여 사용할 때 많이 사용합니다. 

 

$tablet: 968px;
$mobile: 568px;

 
 
@mixin md-screen {
  @media screen and (min-width: #{$tablet}) {
    @content;
  }
}
 
@mixin sm--screen {
  @media screen and (max-width: #{$mobile}) {
    @content;
  }
}

 

.section {
  padding: 0; 
  @include sm-screen {
    padding: 10
    /* 모바일 화면에서 적용할 스타일들 */
  }
  @include md-screen {
    padding: 15px;
    /* 태블릿 화면에서 적용할 스타일들 */
  }
 }

 

 

이외에도 자주 쓰이는 믹스인이 궁금하시다면 아래 링크를 한번 둘러보시는 걸 추천드립니다. 

 

 

10 Best Sass Mixins for Web Developers - Developer Drive

Currently, Sass is the most popular CSS preprocessor among web developers. It allows you to introduce programmatic logic to your CSS code and make use of advanced features such as variables, mixins, functions, inheritance, nesting, and others.

www.developerdrive.com

 

처음 정의할 때는 번거로울 수 있으나 규모가 큰 프로젝트를 진행하다 보면 항상 만들어두길 잘했다는 생각이 먼저 나왔기 때문에 이 포스트를 읽고 계시는 개발자님들도 꼭 자주 쓸만한 스타일들은 미리 만들어놓고 시작하기를 추천드립니다.

 

다음 편에서는 코드를 분리하는 방법부터 시작해 SASS의 심화 기능들을 같이 사용해 보도록 하겠습니다.