SCSS - 페이지 테마화

오민영·2023년 2월 20일
1

CSS

목록 보기
22/22
post-custom-banner

💡 CHECK

  • 사전에 테마를 몇 가지 지정해두고 사용자가 선택하게 하는지?
    • 테마 별로 컬러 지정 필요 (기본, 다크테마, 라이트테마 등등)
    • 최상단 html에 클래스를 부여하면, 테마에 맞춰 일괄 변경됨
  • 사용자가 컬러 하나를 선택하면 그 컬러에 따라 채도/명도/밝기 등 단위로 일괄 변경되도록 설정하는지?
    • 컬러 하나로 응용이 가능한 기술 검토 필요
      • 색상의 채도 / 밝기 조절 (hsla)을 설정하는 방법
  • 사전에 변경할 요소를 지정해서 그 단위만 사용자가 하나하나 설정하는 건지?
    • 어떤 요소만 컬러를 변경되도록 할지 논의 필요

들어가기 전에

▪️ CSS - var( )

css var() 함수는 사용자 지정 속성, css 변수의 값을 다른 속성의 값으로 지정할 때 사용한다.

→ SCSS의 변수 선언과 유사하다. ($primary: #08c;)

// var(값을 가져올 사용자 지정 속성의 이름, 대체 값-속성이 유효하지 않으면 디폴트 값)
var(<custom-property-name>, <declaration-value>)

// 예시
var(--header-color, blue);

<custom-property-name>

  • 두 개의 대시로 시작하는 사용자 지정 속성의 이름을 나타내는 식별자

<declaration-value>

  • 주어진 사용자 지정 속성이 유효하지 않으면 대신 사용할 대체 값
  • 짝 없이 닫는 괄호, 세미콜론, 느낌표 등 특별한 의미를 가진 문자 제외한 모든 문자 사용 가능

[예시 1]

  :root{
      --main-bg-color: pink;
  }

  body{
      background-color: var(--main-bg-color)
  }

[예시 2]

  .component .header{
      color: var(--header-color, blue);
  }

  .component .text{
      color: var(--text-color, black);
  }

  .component {
      --text-color: #080;
  }

▪️ SCSS

SCSS - Mixin & Function

[예시]

// 선언 
@mixin 믹스인명($매개변수){
	// ...
}

@function 함수명($매개변수){
	@return;
}

// 호출
.style{
	@include 믹스인명(인수);
}

.style{
	함수명(인수)
}

SCSS - map

[예시]

$theme-colors: (
  'primary': (
    'base': #384ea9,
    'light': #e4efff,
    'dark': #273677
  ),
  'accent': (
    'base': #f08110,
    'light': #ff8100,
    'dark': #e47f17
  ),
  'foreground': (
    'base': #393939,
    'light': #6e6e6e,
    'dark': #111
  ),
  'background': (
    'base': #f8f5f5,
    'light': #fff,
    'dark': #ddd
  )
);

@function theme-color($key: 'primary', $variant: 'base') {
  $map: map-get($theme-colors, $key);
  @return map-get($map, $variant);
}

.sample{
	background-color: theme-color('foreground', 'light');
	// #6e6e6e
}

map-get(map, key)

  • map에서 지정한 key의 값을 반환한다.
map-get($theme-colors, "primary", "base")
// #384ea9
map.get($theme-colors, "primary", "base")
// #384ea9

map-get($theme-colors, "primary", "like")
// null

map-has-key(map, key)

  • map이 지정한 key를 갖고 있는지 여부를 체크한다.
  • true / false
map-has-key($theme-colors, "primary", "base")
// true
map.has-key($theme-colors, "primary", "base")
// true

map-keys(map)

  • map의 모든 key 리스트를 반환한다.
$font-weights: ("regular": 400, "medium": 500, "bold": 700);

map-key($font-weights)
// "regular", "medium", "bold"
map.key($font-weights)
// "regular", "medium", "bold"

map-values(map)

  • map 안의 모든 값 리스트를 반환한다.
$font-weights: ("regular": 400, "medium": 500, "bold": 700);

map-values($font-weights)
// "400", "500", "700"
map.values($font-weights)
// "400", "500", "700"

map-merge(map1, map2…)

  • map1 끝에 map2를 추가한다.

[예시 1]

$font-sizes: ("small": 12px, "normal": 18px, "large": 24px)
$font-sizes2: ("x-large": 30px, "xx-large": 36px)

map-merge($font-sizes, $font-sizes2);
map.merge($font-sizes, $font-sizes2);
// "small": 12px, "normal": 18px, "large": 24px, "x-large": 30px, "xx-large": 36px

[예시 2]

$fonts: (
  "Helvetica": (
    "weights": (
      "lightest": 100,
      "light": 300
    )
  )
);

$heavy-weights: ("medium": 500, "bold": 700);

map.merge($fonts, "Helvetica", "weights", $heavy-weights);
// (
//   "Helvetica": (
//     "weights": (
//       "lightest": 100,
//       "light": 300,
//       "medium": 500,
//       "bold": 700
//     )
//   )
// )

map-remove(map, key..)

  • map에 해당하는 key를 삭제한다.
$font-weights: ("regular": 400, "medium": 500, "bold": 700);

@debug map.remove($font-weights, "regular"); // ("medium": 500, "bold": 700)
@debug map.remove($font-weights, "regular", "bold"); // ("medium": 500)
@debug map.remove($font-weights, "bolder");
// ("regular": 400, "medium": 500, "bold": 700)

▪️ Reference


테마 지정 방법

▪️ css var()와 scss 함수를 사용해서 테마를 설정하기

_set-color.scss

  1. 테마 적용 할 컬러 변수 (두 번째 인자가 디폴트 컬러 값)
$primary: var(--primary-color, #D92962);
$secondary: var(--secondary-color, #091f63);
$tertiary: var(--tertiary-color, #0B78C8);
$negative: var(--negative-color, #EB1000);
  1. 테마 이름(default..) - 테마 별 컬러 셋 (primary, secondary...)
$config: (
  default: (
    primary: $primary,
    secondary: $secondary,
    tertiary: $tertiary,
    negative: $negative
  ),
  dark: (
    primary: #000,
    secondary: red,
    tertiary: #fff,
    negative: red
  ),
  light: (
    primary: blue,
    secondary: yellow,
    tertiary: purple,
    negative: pink
  )
);

_set-theme.scss

  1. set-color.scss 에서 지정한 key를 가지고 있는 경우, 그 key 값을 출력한다.
@function setColor($map, $object, $style) {
  @if map-has-key($map, $object) {
    @return map-get(map-get($map, $object), $style);
  }
  @warn "The key ´#{$object} is not available in the map.";
  @return null;
}
  1. $config의 $key 값(default / dark / light)이 있을 경우, 마지막 인자 값(primary / secondary ...) 을 출력한다.
@mixin setTheme($key){
  --primary-color: #{setColor($config, $key, primary)};
  --secondary-color: #{setColor($config, $key, secondary)};
  --tertiary-color: #{setColor($config, $key, tertiary)};
  --negative-color: #{setColor($config, $key, negative)};
}
  1. default, dark, light가 $theme으로(= $key) 들어가서 theme 믹스인을 실행한다.
@each $theme in default, dark, light{
  html.#{$theme}-theme{
    @include setTheme($theme);
  }
}
  1. html에 테마 클래스를 넣어주면 해당 컬러 값으로 일괄 변경된다.
<html class="dark-theme"></html>

Reference

SCSS로 테마 변경하기

theming-scss-tutorial

A successful sass theme structure


▪️ root 파일에서 data-theme 설정

  1. nuxt.js에서 document data-theme 속성 세팅
import { useEffect } from "react";
import "../styles/globals.scss";
import type { AppProps } from "next/app";
import Head from "next/head";

function MyApp({ Component, pageProps }: AppProps) {

  useEffect(() => {
    document.documentElement.setAttribute("data-theme", "light");
  }, []);

  return (
    <>
      <Head>
        <title>MeetMeet</title>
        <meta charSet="utf-8"></meta>
      </Head>
      <Component {...pageProps} />
    </>
  );
}

export default MyApp;
  1. 컬러값 지정 (color.scss)
$text-color-1: #232323;
$bg-color-1: #fff;
$btn-color-1: #FE016C;

$text-color-2: #fff;
$bg-color-2: #232323;
$btn-color-2: #FFBD07;
  1. 테마 별 컬러 지정 (theme.scss)
@use "./color.scss" as *;

html[data-theme="light"] {
  --color-text: #{$text-color-1};
  --color-background: #{$bg-color-1};
  --color-btn : #{$btn-color-1};
}
  
html[data-theme="dark"] {
  --color-text: #{$text-color-2};
  --color-background: #{$bg-color-2};
  --color-btn : #{$btn-color-2};
}
  1. 컬러값 변수 사용하고, nuxs.js에서 document data-theme 설정하면 그 테마에 맞게 변경됨
@use "./themes.scss" as *;

html,
body {
  background-color: var(--color-background);
}

a {
  color: var(--color-text);
  text-decoration: none;
}

button {
  backrgound-color: var(--color-btn);
}

* {
  box-sizing: border-box;
}

// ...

Reference

https://velog.io/@aeong98/SCSS로-다크모드-구현해보기


▪️ hsla 을 사용해서 채도 / 색조 / 밝기 조절

hsla(hue, saturation, lightness, alpha)

* hue(색조: 0-360)
- 120: 빨간색
- 240: 녹색
    
* saturation(채도: 0-100%)
- 0%: 회색
- 100%: 풀컬러
    
*lightness(밝기: 0-100%)
- 0%: 검은 색
- 100%: 흰색
    
*alpha(투명도: 0-1)

기본 —base-blue 변수를 사용해서 블루 색상 계층 별로 정의할 수 있다.

:root{
	--base-blue: 222, 89%;
	--main-blue: hsla(var(--base-blue), 55%, 100%);
	--secondary-blue: hsla(var(--base-blue), 45%, 100%);
	--main-blue-transparent: hsla(var(--base-blue), 55%, 10%);

	// ...
	--palette-blue-50: hsla(var(--base-blue), 50%, 100%);
	// ...

	--primary: hsla(var(--palette-blue-50), 100%);
	--emphasis: hsla(var(--palette-blue-50), 8%);
}

Reference

https://kjwsx23.tistory.com/684

profile
이것저것 정리하는 공간
post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 10월 5일

안녕하세요! 비슷한 고민을 하던 차에 큰 도움이 되었습니다. 감사합니다! 한가지 여쭤보고 싶은데요
css var()와 scss 함수를 사용해서 테마를 설정하기 <- 이 부분을 따라서 해봤는데
dark / light 같은 경우에 CSS 변수들의 등록이 잘 되는데요,
default 에서 --primary-color: var(--primary-color, #D92962); 이런 식으로 변환이 되는데
테마에 적용시킬 색상 변수가 다시 테마를 참조하고 있어서 그런지 대체값으로도 적용이 안되더라구요
이부분 동일하게 겪으셨는지, 대안으로 어떻게 생각하시는지 궁금합니다.

답글 달기