점점 다크모드를 적용하는 사이트들이 늘어나고 있는데, Sass를 사용하여 다크모드를 쉽게 적용할 수 있게 코드를 만들어 봤습니다.
우선 일반 컬러 테마와 다크모드 테마를 $light-theme와 $dark-theme 맵에 각각 선언합니다. (4-13줄)
그리고 위의 맵을 사용해서 CSS에서 var()를 사용하기 위한 변수를 선언하고, 미디어쿼리도 적용해 줍니다. (15-25줄)
그러면 CSS의 1-13줄과 같이 변수가 생성됩니다.
이제 본격적으로 믹스인을 생성합니다. (28-41줄)
기본적으로 color-theme(key: value)의 형태로 한 개 이상의 키:밸류 쌍으로 된 속성을 전달할 수 있습니다. 그러나 border나 background 등과 같이 색상 이외에 다른 속성도 같이 설정할 필요가 있는 경우에 color, prefix, suffix의 속성을 가진 맵을 사용할 수 있습니다.
43-53줄과 같이 믹스인을 사용하면 CSS의 14-29줄에 해당하는 코드를 생성합니다.
같은 속성이 두 개씩 만들어 지는 것은 CSS의 변수나 미디어쿼리를 지원하지 않는 구형 브라우저에서는 첫 번째 속성의 컬러를 사용하고, 지원하는 브라우저는 변수와 미디어쿼리가 적용되도록 하기 위해서 입니다.
IE와 같은 구형 브라우저를 지원할 필요가 없다면 31, 37줄의 코드는 삭제하면 됩니다.
@use "sass:map";
@use "sass:meta";
$light-theme: (
bgc: #fff,
txt: #333,
brd: #ff6
);
$dark-theme: (
bgc: #333,
txt: #eee,
brd: #339
);
:root{
@each $k, $v in $light-theme{
#{"--" + $k}: #{$v};
}
}
@media (prefers-color-scheme: dark){
:root{
@each $k, $v in $dark-theme{
#{"--" + $k}: #{$v};
}
}
}
@mixin color-theme($args...){
@each $k, $v in meta.keywords($args){
@if(meta.type-of($v) == "string"){
#{$k}: map.get($light-theme, $v);
#{$k}: #{"var(--" + $v + ")"};
}@else if(meta.type-of($v) == "map"){
$c: map.get($v, color);
$p: map.get($v, prefix);
$s: map.get($v, suffix);
#{$k}: $p map.get($light-theme, $c) $s;
#{$k}: $p #{"var(--" + $c + ")"} $s;
}
}
}
html, body{
@include color-theme($color: txt, $background-color: bgc);
}
.border{
@include color-theme($border: (prefix: 1px solid, color: brd));
}
.background{
@include color-theme($background: (color: bgc, suffix: url(bg.jpg) no-repeat 50% 50%));
}
:root {
--bgc:#fff;
--txt:#333;
--brd:#ff6;
}
@media (prefers-color-scheme: dark) {
:root {
--bgc:#333;
--txt:#eee;
--brd:#339;
}
}
html, body {
color: #333;
color: var(--txt);
background-color: #fff;
background-color: var(--bgc);
}
.border {
border: 1px solid #ff6;
border: 1px solid var(--brd);
}
.background {
background: #fff url(bg.jpg) no-repeat 50% 50%;
background: var(--bgc) url(bg.jpg) no-repeat 50% 50%;
}