SCSS를 사용하면 스타일시트에서 쉽게 재사용할 수 있는 변수, 믹스인 및 함수를 정의할 수 있습니다. 이렇게 하면 코드 모듈성과 재사용성이 향상되어 테마를 더 쉽게 만들고 유지 관리할 수 있습니다. 테마별 변수 집합을 정의하고 스타일시트 전체에 일관되게 적용할 수 있습니다. 재사용 가능한 스타일을 정의하고 이를 다른 요소나 구성 요소에 적용하여 CSS 코드베이스를 단순화하고 유지 관리하기 쉽게 만들 수 있습니다.
Dart Sass의 map기능을 활용
// _variables.scss
$theme-light: (
bg: #ffffff,
text: #333333,
primary: #007bff,
secondary: #6c757d,
);
$theme-dark: (
bg: #333333,
text: #ffffff,
primary: #00ff7f,
secondary: #fa8072,
);
이제 이 변수를 사용하여 기본적인 스타일을 만들 수 있습니다.
// _base.scss
@import 'variables';
body {
background: map-get($theme-light, bg);
color: map-get($theme-light, text);
}
.button {
background: map-get($theme-light, primary);
color: map-get($theme-light, text);
}
.secondary-button {
background: map-get($theme-light, secondary);
color: map-get($theme-light, text);
}
이제 이 테마를 바꾸는 믹스인을 만들어 보겠습니다.
// _mixins.scss
@import 'variables';
@mixin theme($theme: $theme-light) {
body {
background: map-get($theme, bg);
color: map-get($theme, text);
}
.button {
background: map-get($theme, primary);
color: map-get($theme, text);
}
.secondary-button {
background: map-get($theme, secondary);
color: map-get($theme, text);
}
}
믹스인을 사용하여 다크 테마를 적용해봅시다.
// style.scss
@import 'base';
@import 'mixins';
body.dark-theme {
@include theme($theme-dark);
}
이 방식은 효과적인거 같아도 사실 번거롭고 내용이 많아지고 관리할 파일이 많아질수록 효율적이지가 않습니다.
사실 실무에서는 하나에서 많게 수십개의 SCSS파일에 하나의 아이디를 추가하거나 클래스를 추가하여 전체 클래스를 변경하는 방법을 많이 사용하게 됩니다. 이럴 경우 SCSS에서 제공하는 @each 기능을 사용하면 한 파일안에서 여러 테마를 테마맵 파일을 통해 관리 가능합니다.
@each ... in... 사용하기
// 각 테마에 대한 색상 정의
$themes: (
light: (
primary: #007bff,
secondary: #6c757d,
),
dark: (
primary: #00ff7f,
secondary: #fa8072,
),
);
// 각 테마를 순회하면서 해당 테마에 대한 CSS를 생성
@each $theme-name, $theme-colors in $themes {
$primary: map-get($theme-colors, primary);
$secondary: map-get($theme-colors, secondary);
// theme id selector 추가
##{$theme-name} {
// 각 SCSS 파일을 import
@import "file1";
@import "file2";
@import "file3";
// ...
}
}
이 코드에서 file1, file2, file3 등은 완성된 SCSS 파일의 이름을 나타냅니다. 각 SCSS 파일 내에서는 $primary와 $secondary 변수를 사용하여 색상을 지정합니다. 이런 방식으로, 각 테마별로 SCSS 파일을 재사용하면서도 테마에 따라 다른 색상을 적용할 수 있습니다.
이 방식의 주요 제한 사항은 모든 SCSS 파일이 각 테마에 대해 전체적으로 중복될 수 있다는 점입니다. 이는 결과 CSS 파일의 크기를 크게 늘릴 수 있으므로, 파일 크기가 중요한 경우에는 다른 방법을 고려해야 할 수 있습니다.
@each와 in사이의 변수는 각각 맵의 첫번째 프로퍼티와 두번째 프로퍼티를 가리킵니다.
map의 첫번째는 light와 dark이며 테마 이름으로 사용됩니다. 두번째는 각각의 프로퍼티 하위의 프로퍼티인 Color 값들입니다. 따라서 $theme-name은 lihgt와 dark를 말하며, $theme-colors는 primary, secondary를 말합니다.
파일 크기가 걱정된다면 theme.scss 파일을 만들고 그 안에서 해당 클래스 하위에 있을 경우 CSS Custom Properties에 컬러 값을 적용해서 사용할 수 있습니다.
// 두 단계로 구성된 맵 데이터
$colors: (
red: (
text: #f00,
background: red
),
green: (
text: #0f0,
background: green
),
blue: (
text: #00f,
background: blue
)
);
$textColor : var(--text-color);
$backgroundColor : var(--background-color);
// @each 디렉티브 사용
@each $theme-name, $theme-prop in $colors {
body {
&.theme-#{$theme-name} { //.theme-red, .theme-green, .theme-blue의 하위요소에 사용될 프로퍼티즈 적용
--text-color: #{map-get($theme-prop, text)} !important; // !important 사용하기
--background-color: #{map-get($theme-prop, background)};
}
.some-bg {
background-image: url('images/theme-bg-#{$theme-name}.png');
}
}
}
적용시에는 반드시 인터폴레이션을 사용하여 적용해 줍니다. 맵의 키는 map-get을 사용하지 않아도 되지만 value 값은 반드시 map-get($theme-prop, text)처럼 map-get을 통해서 사용하려는 value의 키를 지정해야 합니다.
이렇게 작성하면 .theme-red, .theme-green, .theme-blue 하위에서 사용되는 $textColor, $backgroundColor의 값은 각각 맵에 지정한 컬러로 변경되어 적용됩니다.
이후 class명을 변경하는 스크립트 등으로 클래스를 적용하면 테마가 적용됩니다.
(페이지 하단 스크립트 참고)
CSS Custom Properties (또는 CSS Variables)를 사용
각 테마에 대한 스타일 규칙을 반복할 필요 없이 CSS 변수 값을 변경하여 색상 스킴을 전환할 수 있습니다.
Custom Properties는 값을 정의한 선택자의 하위에 모두 적용되는 특징이 있으므로 테마를 아이디나 클래스명으로 정하고 설정할 수 있습니다.이 방법은 Internet Explorer 등 일부 오래된 브라우저에서는 지원하지 않습니다.
:root {
--primary: #007bff;
--secondary: #6c757d;
}
#dark {
--primary: #00ff7f;
--secondary: #fa8072;
}
// 기존의 SCSS 파일들
@import "file1";
@import "file2";
@import "file3";
// ...
// 사용하기 1
.example {
background-color: var(--primary);
color: var(--secondary);
}
// 사용하기 2
$primary: var(--primary);
$seconday: var(--secondary);
.example {
background-color: $primary
color: $secondary;
}
// 코드가 길어질 경우 var()를 사용하는 것보다 코드 사용시 편리함
CSS Custom Properties와 Javascript를 활용한 방법
보통 테마 적용시 사용자가 원하는 테마로 변경하는 기능을 제공하게 됩니다. 그럴 경우 스크립트를 통해 이벤트를 제어하여 테마 변경을 지원합니다.
/* CSS */
:root {
--primary: #007bff;
--secondary: #6c757d;
}
body {
background-color: var(--primary);
color: var(--secondary);
}
button {
background-color: var(--primary);
color: var(--secondary);
}
그런 다음 JavaScript를 사용하여 테마를 변경합니다.
// JavaScript
function switchTheme(theme) {
const rootStyle = document.documentElement.style;
if (theme === 'dark') {
rootStyle.setProperty('--primary', '#00ff7f');
rootStyle.setProperty('--secondary', '#fa8072');
} else if (theme === 'light') {
rootStyle.setProperty('--primary', '#007bff');
rootStyle.setProperty('--secondary', '#6c757d');
}
// ...and so on for other themes
}
// 테마 변경 예시
switchTheme('dark');
가장 추천하는 방법으로는 다음과 같이
CSS Custom Properties와 SCSS의 변수를 활용하는 방법입니다.
간단한 컬러값의 경우 이와 같이 변경하지만 복잡한 경우 SCSS로 ID나 Class명으로 테마가 변경되도록 설정해 놓고, 스크립트를 통해 ID나 Class를 변경하는 방법을 더 많이 사용합니다.
/* SCSS */
#light {
--primary: #007bff;
--secondary: #6c757d;
}
#dark {
--primary: #00ff7f;
--secondary: #fa8072;
}
$primary:var(--primary);
$secondary:var(--secondary);
// 사용시
#light .sub-element {
background-color: $primary; //#007bff
color: $secondary;//#6c757d
}
#dark .sub-element {
background-color: $primary;//#00ff7f
color: $secondary;//#fa8072
}
// 테마로 사용될 선택자를 포함한 선택자들은 테마 컬러가 적용됩니다.
자바스크립트로 테마 적용에 사용될 id를 변경합니다.
// JavaScript
function switchTheme(theme) {
document.body.id = theme;
// 또는
const element = document.getElementById("myElement");
element.id = theme;
// setAttribute로 변경하기
// element.setAttribute("id", theme);
}
// 테마 변경 예시
switchTheme('dark');
만약 테마를 한 사이트내에서 각 섹션별로 다르게 줘야 한다면 아래와 같이 mixin와 include를 통해 적용할 수 있습니다.
// _theme.scss
@mixin theme1 {
$primary-color: #ff0000;
$secondary-color: #00ff00;
// 추가할 변수들
}
@mixin theme2 {
$primary-color: #0000ff;
$secondary-color: #ffff00;
// 추가할 변수들
}
// mixin을 통해 컬러 테마 변수들을 전달합니다.
// main.scss
@import 'theme'
#selector1 {
@include theme1;
// CSS
}
#selector2 {
@include theme2;
// CSS
}
SCSS통한 테마는 CSS Custom Properties가 사용되기 시작하면서 다양하게 작성할 수 있게 되었습니다.
<body style="--prirmay: #00ff00"> 처럼 작성하고 사용시 CSS에서 var(--primary)와 같이 사용하거나 SCSS인 경우 $primary: var(--primary)와 같이 사용됩니다.
document.body.style.setProperty등을 통해 값을 직접 변경하는 방법을 사용 할 수 있습니다.
<body style="--primary:#00ff00;">...
// JavaScript
function switchTheme(theme) {
const rootStyle = document.body.style;
if (theme === 'dark') {
rootStyle.setProperty('--primary', '#00ff7f');
rootStyle.setProperty('--secondary', '#fa8072');
} else if (theme === 'light') {
rootStyle.setProperty('--primary', '#007bff');
rootStyle.setProperty('--secondary', '#6c757d');
}
// ...and so on for other themes
}
// 테마 변경 예시
switchTheme('dark');
CSS Property와 var()를 활용해서 테마를 작성하게 되면 transparentize 처럼 rgb 값을 기준으로 값을 지정하는 기능은 사용할 수가 없습니다. 디자이너들이 색 사용에 있어 색을 지정하는게 아니라 투명도를 바꾸는 방법으로 컬러 값을 쓰는 경우가 많습니다.
그럴 경우에는 var()를 통한 색 지정방법은 피하는게 좋습니다.
$themes: (
theme1: (
primary: #ff0000,
secondary: #00ff00,
tertiary: #0000ff,
),
theme2: (
primary: #ff00ff,
secondary: #00ffff,
tertiary: #ffff00,
),
theme3: (
primary: #000000,
secondary: #ffffff,
tertiary: #888888,
)
);
@each $theme-name, $theme in $themes {
.#{$theme-name} {
$primary: map-get($theme, 'primary');
$secondary: map-get($theme, 'secondary');
$tertiary: map-get($theme, 'tertiary');
body {
background-color: $primary;
color: $secondary;
}
h1 {
color: $tertiary;
}
.transparent-bg {
background-color: transparentize($primary, 0.5);
}
}
}
투명도를 활용해야 하는 상황이라면 위 처럼 var(--primary)와 같은 값을 사용하지 말고 직접 $primary에 컬러값을 지정해야 합니다. 테마가 적용될 부분이 적다면 위처럼 작성하는 것도 좋지만 테마가 작용될 부분이 많다면 믹스인을 활용하는게 좋습니다.
$themes: (
theme1: (
primary: #ff0000,
secondary: #00ff00,
tertiary: #0000ff,
),
theme2: (
primary: #ff00ff,
secondary: #00ffff,
tertiary: #ffff00,
),
theme3: (
primary: #000000,
secondary: #ffffff,
tertiary: #888888,
)
);
@mixin theme-variables($theme-name) {
$theme: map-get($themes, $theme-name);
$primary: map-get($theme, 'primary');
$secondary: map-get($theme, 'secondary');
$tertiary: map-get($theme, 'tertiary');
}
map을 활용해 컬러 값을 mixin에 매핑한후 해당 mixin에 테마명을 작성해서 include를 적용합니다
.theme1 {
@include theme-variables('theme1');
body {
background-color: $primary;
color: $secondary;
}
h1 {
color: $tertiary;
}
.transparent-bg {
background-color: transparentize($primary, 0.5);
}
}
.theme2 {
@include theme-variables('theme2');
body {
background-color: $primary;
color: $secondary;
}
h1 {
color: $tertiary;
}
.transparent-bg {
background-color: transparentize($primary, 0.5);
}
}
.theme3 {
@include theme-variables('theme3');
body {
background-color: $primary;
color: $secondary;
}
h1 {
color: $tertiary;
}
.transparent-bg {
background-color: transparentize($primary, 0.5);
}
}
이렇게 작성하면 한 파일안에서 관리를 못한다는 단점이 존재하게 됩니다.
각각의 방법에 장단점이 존재하는 만큼 컬러값을 디자인에서 어떻게 활용하는지에 따라 선택해야 합니다.
'HTML, CSS' 카테고리의 다른 글
Print용 CSS 설정 (0) | 2023.08.07 |
---|---|
최신기능을 지원하는 CSS 전처리기 Dart SCSS (0) | 2023.07.23 |
:is() 의사 클래스 (0) | 2023.07.09 |
접근성을 위한 미디어 쿼리 사용 (0) | 2023.07.02 |
HTML Input 기본 버튼 아이콘 숨기기 (0) | 2023.06.22 |
댓글