들어가며
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);
}
이렇게 하면 아래와 같은 결과를 얻을 수 있다.
그럼 이제 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의 테마 작업에 대한 부분을 해결한 거 같아 기분이 좋았고, 혹시 나와 같은 고민을 하고 있을 누군가에게 도움이 될까 싶어 내용 공유 및 한 번 더 작업 내용을 정리하고자 글을 작성하였다.
참고 문서