🚀   새로운 블로그로 이전했습니다.

다크모드, 더 프로처럼 활용하기

2023.05.22
5분

개인적으로 다크모드를 접하면서 경험한 것을 전체적으로 정리해 보았습니다.

다크모드 CSS

다양한 방식으로 다크모드를 다룰 수 있습니다.
서비스 상황에 맞춰 적절한 방법을 선택하는 것이 좋습니다.

(초급) 미디어 쿼리 활용하기

.txt_g {
  color: #111;
}

@media (prefers-color-scheme: dark) {
  .txt_g {
    color: #fff;
  }
}

prefers-color-scheme를 통해서 사용자의 기기 환경이 다크모드인지 알 수 있습니다.
css 만으로 손쉽게 사이트에 다크모드를 적용할 수 있습니다.

(중급) .dark 활용하기

.txt_g {
  color: #111;
}

.dark .txt_g {
  color: #fff;
}

body 혹은 html 태그에 dark 클래스를 추가하여 스타일을 적용하는 방법입니다.
js의 도움을 받아 동적으로 다크모드를 설정할 수 있습니다.

유의할 점은 css 작성할 때 css 적용 우선 순위를 고려해야 합니다.

/* .dark로 선언한 스타일을 덮어씌우게 된다.. */
.main_section .tit_cont .txt_g {
  color: #000;
}

(고급) css 변수 사용하기

:root {
  --foreground: #111;
}

.dark {
  --foreground: #fff;
}

.txt_g {
  color: var(--foreground);
}

이전 설정에 비해 사용이 훨씬 간편해집니다.
초기 색상 변수만 선언해두면, 추후 개별적로 css을 덮어 씌울 필요가 없습니다.

다만, 디자인 시스템이 필수로 요구됩니다.
같은 글을 어디서는 #1f1f1f을 쓰고 어디서는 #ffffff을 적용해야 한다면 꽤나 머리 아파집니다.

추가적으로 IE에선 이를 지원하지 않는 점을 유의해야 합니다.

(번외) tailwindcss

별다른 설정 없이 dark:text-white 형태로 바로 스타일을 적용할 수 있습니다.
기본으로 media-query문법으로 적용되지만, .dark 클래스명으로 적용하고 싶다면 아래 설정을 추가하면 됩니다.

module.exports = {
  darkMode: 'class',
  // ...
};

(번외) 다크모드 무효화 지대

특정 영역만 다크모드를 적용되지 않도록 하고 싶을 때가 있습니다.
그 핵심은 바로 :where()을 사용하는 것입니다.

.dark .txt_g:not(:where([class~='no-dark'] *)) {
  color: #fff;
}

생각보다 css 지원 범위가 제한적인 것이 흠입니다. 현재 기준으로 전세계 92% 브라우저 지원

아래 글을 추가로 참고해보면 좋습니다.

다크모드 JS

htmldark 클래스를 추가해주는 역할입니다.
미디어쿼리 API를 활용하는 것이 핵심입니다.

window.matchMedia('(prefers-color-scheme: dark)').matches;
function applyDarkMode(isDarkMode) {
  if (isDarkMode) {
    document.documentElement.classList.add('dark');
  } else {
    document.documentElement.classList.remove('dark');
  }
}
function setDarkMode(mode) {
  if (mode === 'system') {
    localStorage.removeItem('theme');
    // ...
  } else {
    localStorage.theme = mode;
    applyDarkMode(mode === 'dark');
  }
}

addEventListener

safari 14 이하에서 MediaQueryList.addEventListener를 지원하지 않는 점을 주의해야 합니다.

function listenDarkMode(isDarkMode) {
  const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
  mediaQuery.addEventListener
    ? mediaQuery.addEventListener('change', (e) => handleMediaQuery(e.matches))
    : mediaQuery.addListener((e) => handleMediaQuery(e.matches));
}

페이지 이동시 화면 번쩍임 대응

페이지 이동시 화면이 번쩍이는 현상이 발생될 수 있습니다.

대응하는 핵심 방법은 바로 화면을 그리기 전에 다크모드 관련 설정을 적용하는 것입니다.
<head> 태그에서 혹은 <body> 태그 최상단에서 다크모드를 여부 설정을 적용하면 됩니다.

No flash on load (both SSR and SSG)

NextJS의 next-themes에서도 관련된 내용을 확인할 수 있습니다.

번외

멋진 다크모드 사이트 탐방해보면 많은 영감을 얻을 수 있습니다.