main-logo

SCSS THEME

SCSS로 테마작업 하기

profile
TY
2023년 08월 19일 · 0 분 소요

들어가며

CSS를 활용한 테마 작업에서는 CSS 변수를 사용하여 class를 이용하여 간단하게 테마 변경이 가능하고, 테마별 컬러 정의만 잘 되어있으면 그다지 까다롭지 않다.

그런데 CSS를 보다 더 편하고, 유용한 기능들을 사용하기 위해 SCSS를 사용하는 경우가 굉장히 많은데 SCSS에서는 CSS에서 하던 테마 작업이 생각보다 쉽게 구현되지 않는다.
class 제어로 간편하게 테마의 컬러셋을 변경하고, SCSS의 장점들을 모두 사용하고 싶은데 그게 참 마음대로 되지 않았었다.

그러던 와중 얼마 전 흥미로운 블로그 글을 하나 발견하였고, 때마침 SCSS를 사용하는 프로젝트에서 갑작스럽게 테마가 추가가 되면서 발견한 블로그 글을 시도해 볼 수 있었다.
오래된 블로그 글이었지만 뭔가 그동안 바라왔었던 테마의 작업 환경이 실현할 수 있을 것 같다는 큰 힌트가 되었고, 결과적으로는 나름 성공적이어서 같은 고민을 하는 사람들에게 도움이 될까 싶어 내용을 공유하려 한다.

_variables.scss


가장 먼저 해야 할 일은 바로 테마 컬러셋을 만드는 것이다.
항상 하던 데로 _variables.scss에 컬러셋을 선언하면 되는데, 우리는 CSS에서 했듯이 CSS 변수를 사용하여 테마 작업을 하므로 SCSS 변수에 그에 상응하는 CSS 변수명을 지정해 주면 된다.

/* Basic Color */
$white: #fff;
$black: #000;

/* Gray */
$gray100: --gray100;
$gray90: --gray90;
$gray80: --gray80;
$gray70: --gray70;
$gray60: --gray60;
$gray50: --gray50;
$gray40: --gray40;
$gray30: --gray30;
$gray20: --gray20;
$gray10: --gray10;
$gray00: --gray00;

/* DayState */
$color-warning: --color-warning;
$color-caution: --color-caution;
$color-interest: --color-interest;
$color-work: --color-work;
$color-over: --color-over;
$color-zero: --color-zero;
$color-vacation: --color-vacation;

/* popup */
$popup-bg: --popup-bg;
$popup-chart: --popup-chart;

그러고 나서 다크/라이트 테마별 컬러셋을 지정해줘야 하는데, SCSS mixin을 통해 CSS 변수를 생성할 계획이니 아래 코드를 참고해서 컬러셋을 선언하면 된다.

/* Theme */
$theme-dark: (
  /* Gray */ $gray100: #fff,
  $gray90: #eaeef2,
  $gray80: #cbd2d9,
  $gray70: #a6adb5,
  $gray60: #8c939d,
  $gray50: #737985,
  $gray40: #5d606d,
  $gray30: #484a57,
  $gray20: #32323c,
  $gray10: #1d1c21,
  $gray00: #161519,
  /* DayState */ $color-warning: #fa1400,
  $color-caution: #fa6d5e,
  $color-interest: #fab7b0,
  $color-work: #227066,
  $color-over: #ffdd5c,
  $color-zero: #888,
  $color-vacation: #03c500,
  /* popup */ $popup-bg: #484a57,
  $popup-chart: #227987
);

$theme-light: (
  /* Gray */ $gray00: #fff,
  $gray10: #eaeef2,
  $gray20: #cbd2d9,
  $gray30: #a6adb5,
  $gray40: #8c939d,
  $gray50: #737985,
  $gray60: #5d606d,
  $gray70: #484a57,
  $gray80: #32323c,
  $gray90: #1d1c21,
  $gray100: #161519,
  /* DayState */ $color-warning: #ea3900,
  $color-caution: #f80,
  $color-interest: #ebb200,
  $color-work: #c2e1c2,
  $color-over: #ff1c00,
  $color-zero: #888,
  $color-vacation: #03c500,
  /* popup */ $popup-bg: #8c939d,
  $popup-chart: #a7cfb2
);

이제 테마별 컬러셋은 준비가 끝났다.

_mixin.scss

이제 위에서 언급했던 CSS 변수들을 생성할 차례인데, _mixin.scss 파일에 해당 mixin을 만들면 된다.

// theme
@mixin theme-map($map: ()) {
  @each $key, $value in $map {
    #{$key}: $value;
  }
}

theme.scss

이제 컬러셋도 준비되었고, 이 컬러셋을 활용하여 CSS 변수를 만들어주는 mixin도 준비가 되었으니 위에서 선언한 $theme-dark$theme-light를 mixin의 인자로 전달하여 CSS 변수를 생성하면 된다.

html.light {
  @include theme-map($theme-light);
}

html.dark {
  @include theme-map($theme-dark);
}

이렇게 하면 아래와 같은 결과를 얻을 수 있다.

 

image1.png
테마 CSS 변수 생성 결과

그럼 이제 SCSS에서 다음과 같이 사용할 수 있다.

background: var($gray00);
color: var($gray100);

그런데 아무래도 CSS 변수이다 보니 매번 var 를 사용해야 하는 번거로움이 있었다.
이런 번거로움을 어떻게 해결하면 될까 고민이 있었는데, 그런 와중에 컬러코드가 Hex 코드가 아닌 rgb나 rgba를 사용하려면 어떻게 해야 하지? 라는 고민도 생겨났고, 앞에서의 var와 함께 한 번에 해결해 보기로 하였다.

Hex 코드로 선언하고, 변수에는 rgb 코드로 저장하기

우선 컬러셋을 만들 때 애초에 rgb 코드로 만들어도 되긴 하나… 개인적으로 선호하는 스타일이 아니었다. Hex 코드로 컬러를 사용하는 게 익숙했고 앞으로도 웬만해선 rgb 코드를 사용하진 않을 거 같아 컬러셋을 만들 때는 Hex 코드로 만들지만 실제로는 rgb 코드로 변환하는 흔하디흔한 scss function을 만들어 컬러셋을 지정하는 코드를 바꿔줬다.

@function to-rgb($color) {
  @return #{red($color) + ', ' + green($color) + ', ' + blue($color)};
}

/* Theme */
$theme-dark: (
  /* Gray */ $gray100: to-rgb(#fff),
  $gray90: to-rgb(#eaeef2),
  $gray80: to-rgb(#cbd2d9),
  $gray70: to-rgb(#a6adb5),
  $gray60: to-rgb(#8c939d),
  $gray50: to-rgb(#737985),
  $gray40: to-rgb(#5d606d),
  $gray30: to-rgb(#484a57),
  $gray20: to-rgb(#32323c),
  $gray10: to-rgb(#1d1c21),
  $gray00: to-rgb(#161519),
  /* DayState */ $color-warning: to-rgb(#fa1400),
  $color-caution: to-rgb(#fa6d5e),
  $color-interest: to-rgb(#fab7b0),
  $color-work: to-rgb(#227066),
  $color-over: to-rgb(#ffdd5c),
  $color-zero: to-rgb(#888),
  $color-vacation: to-rgb(#03c500),
  /* popup */ $popup-bg: to-rgb(#484a57),
  $popup-chart: to-rgb(#227987)
);
$theme-light: (
  /* Gray */ $gray00: to-rgb(#fff),
  $gray10: to-rgb(#eaeef2),
  $gray20: to-rgb(#cbd2d9),
  $gray30: to-rgb(#a6adb5),
  $gray40: to-rgb(#8c939d),
  $gray50: to-rgb(#737985),
  $gray60: to-rgb(#5d606d),
  $gray70: to-rgb(#484a57),
  $gray80: to-rgb(#32323c),
  $gray90: to-rgb(#1d1c21),
  $gray100: to-rgb(#161519),
  /* DayState */ $color-warning: to-rgb(#ea3900),
  $color-caution: to-rgb(#f80),
  $color-interest: to-rgb(#ebb200),
  $color-work: to-rgb(#c2e1c2),
  $color-over: to-rgb(#ff1c00),
  $color-zero: to-rgb(#888),
  $color-vacation: to-rgb(#03c500),
  /* popup */ $popup-bg: to-rgb(#8c939d),
  $popup-chart: to-rgb(#a7cfb2)
);

_function.scss

to-rgb 코드를 보면 rgb(255, 255, 255)로 반환하는 게 아닌 rgb의 숫자 코드인 255, 255, 255를 반환하고 있다. 이는 rgba 등 opacity와 함께 사용하거나 하는 경우를 생각하였고, 애초에 첫 결과물이 var를 사용하고 있었으니, rgb의 숫자만 CSS 변수로 지정하고 이를 활용한 SCSS function을 만들어 rgba를 사용할 수 있게 하였다.

@function theme-rgba($key, $opacity, $map: $theme-dark) {
  @return rgba(var($key), $opacity);
}

@function theme-color($key, $map: $theme-dark) {
  @return rgb(var($key));
}

이제 작업할 때 theme-color를 사용하면 일반적인 컬러를 사용하게 되며, theme-rgba를 사용하여 2번째 인자로 opacity 수치를 함께 지정하여 자유롭게 투명도를 조절할 수 있다.

background-color: theme-color($popup-bg);
background-color: theme-rgba($popup-chart, 0.5);
box-shadow: 0 0 10px theme-rgba($gray00, 0.7);
background: linear-gradient(
  theme-color($color-warning),
  theme-color($color-caution),
  theme-color($color-interest),
  theme-color($color-caution),
  theme-color($color-warning)
);

마치며

SCSS를 사용하면서 테마 작업을 하는 건 그동안은 굉장히 번거로웠으나,(나만 그런가…) 이런 방식을 사용하여(나만 이제 알았나…) 좀 더 편리한 작업을 할 수 있을 거 같다.

우연히 봤던 블로그의 내용과 타이밍 좋았던 프로젝트의 테마 작업으로 인해 그동안의 고민거리 중 하나였던 SCSS의 테마 작업에 대한 부분을 해결한 거 같아 기분이 좋았고, 혹시 나와 같은 고민을 하고 있을 누군가에게 도움이 될까 싶어 내용 공유 및 한 번 더 작업 내용을 정리하고자 글을 작성하였다.

참고 문서