Preferreds-color-scheme: 안녕 어둠, 내 오랜 친구

과대평가된 기능인가요, 아니면 필수 기능인가요? 어두운 모드에 관한 모든 정보와 사용자에게 도움이 되도록 이 모드를 지원하는 방법을 알아보세요.

소개

어두운 모드 이전의 어두운 모드

녹색 화면 컴퓨터 모니터
그린 스크린 (소스)

어두운 모드가 한 바퀴 돌아왔습니다. 개인용 컴퓨팅이 시작된 초기에는 어두운 모드가 선택사항이 아니라 사실이었습니다. 모노크롬 CRT 컴퓨터 모니터는 형광 화면에 전자 빔을 발사하여 작동했으며 초기 CRT에 사용된 형광 물질은 녹색이었습니다. 텍스트가 녹색으로 표시되고 나머지 화면은 검은색이므로 이러한 모델은 녹색 화면이라고도 불렸습니다.

흰색 바탕에 검은색 워드 프로세싱
흰색 바탕에 검은색 (소스)

이후에 도입된 컬러 CRT는 빨간색, 녹색, 파란색 형광체를 사용하여 여러 색상을 표시했습니다. 세 가지 형광체를 모두 동시에 활성화하여 흰색을 만들었습니다. 보다 정교한 WYSIWYG 데스크톱 출판이 등장하면서 가상 문서를 실제 종이와 비슷하게 만드는 아이디어가 인기를 얻었습니다.

WorldWideWeb 브라우저의 흰색 바탕에 검은색 텍스트 웹페이지
WorldWideWeb 브라우저 (소스)

여기에서 디자인 트렌드로서 흰색 바탕에 검은색이 시작되었으며 이 트렌드는 초기 문서 기반 웹으로 이어졌습니다. 최초의 브라우저인 WorldWideWeb(아직 CSS가 발명되지도 않았던 시절)은 이런 식으로 웹페이지를 표시했습니다. 재미있는 사실: 두 번째 브라우저인 터미널 기반 브라우저인 라인 모드 브라우저는 어두운 모드에서 녹색이었습니다. 요즘 웹페이지와 웹 앱은 일반적으로 밝은 배경에 어두운 텍스트로 디자인됩니다. 이는 Chrome을 비롯한 사용자 에이전트 스타일시트에도 하드코딩된 기본 가정입니다.

침대에서 스마트폰을 사용하는 모습
침대에서 사용하는 스마트폰 (출처: Unsplash)

CRT의 시대는 지났습니다. 콘텐츠 소비 및 제작이 백라이트 LCD 또는 에너지 절약형 AMOLED 화면을 사용하는 휴대기기로 전환되었습니다. 더 작고 휴대하기 쉬운 컴퓨터, 태블릿, 스마트폰이 등장하면서 새로운 사용 패턴이 생겨났습니다. 웹 탐색, 재미로 하는 코딩, 고급 게임과 같은 여가 활동은 어두운 환경에서 근무 시간 후에 자주 이루어집니다. 사람들은 밤에 침대에서도 기기를 사용합니다. 어두운 곳에서 기기를 사용하는 사용자가 많아질수록 밝은 배경에 어두운 글꼴의 근본으로 돌아가자는 아이디어가 인기를 얻고 있습니다.

어두운 모드 사용 이유

미적 이유로 인한 어두운 모드

어두운 모드를 좋아하거나 원하는 이유를 묻는 질문에 가장 많이 나오는 대답은 '눈에 부담이 덜 갑니다.' 다음으로 '우아하고 아름답습니다.'가 뒤를 잇습니다. Apple은 어두운 모드 개발자 문서에서 다음과 같이 명시적으로 설명합니다. '밝은 모드 또는 어두운 모드를 사용 설정할지 여부는 대부분의 사용자에게 미적 선택사항이며 주변 조명 조건과 관련이 없을 수 있습니다.'

Mac OS System 7의 CloseView
System 7 CloseView (소스)

접근성 도구로서의 어두운 모드

저시력 사용자와 같이 어두운 모드가 실제로 필요하며 이를 다른 접근성 도구로 사용하는 사용자도 있습니다. 이러한 접근성 도구의 가장 초기 사례는 검은색 바탕에 흰색흰색 바탕에 검은색 전환 버튼이 있는 System 7CloseView 기능입니다. System 7에서는 색상을 지원했지만 기본 사용자 인터페이스는 여전히 흑백이었습니다.

이러한 반전 기반 구현은 색상이 도입되면서 약점을 드러냈습니다. Szpiro et al.시력이 약한 사용자가 컴퓨팅 기기에 액세스하는 방법에 관한 사용자 연구에 따르면 인터뷰에 참여한 모든 사용자가 반전된 이미지를 좋아하지 않았지만 많은 사용자가 어두운 배경에 밝은 텍스트를 선호하는 것으로 나타났습니다. Apple은 이미지, 미디어, 어두운 색상 스타일을 사용하는 일부 앱을 제외하고 디스플레이의 색상을 반전하는 스마트 반전이라는 기능으로 이 사용자 환경설정을 지원합니다.

시력 저하의 특별한 형태는 컴퓨터 비전 증후군(디지털 눈의 피로라고도 함)으로, '컴퓨터(데스크톱, 노트북, 태블릿 포함) 및 기타 전자 디스플레이(예: 스마트폰, 전자 독서기) 사용과 관련된 눈과 시력 문제의 조합'으로 정의됩니다. 청소년이 전자 기기를 사용하는 것, 특히 야간에 전자 기기를 사용하면 수면 시간 단축, 수면 시작 지연, 수면 부족 위험이 증가한다는 제안이 있습니다. 또한 청색광 노출은 일주기 리듬 및 수면 주기의 조절과 관련이 있다는 보고가 많으며, 로젠필드의 연구에 따르면 불규칙한 조명 환경은 수면 부족을 유발하여 기분과 작업 수행에 영향을 줄 수 있습니다. 이러한 부정적인 영향을 제한하려면 iOS의 Night Shift 또는 Android의 Night Light와 같은 기능을 통해 디스플레이 색상 온도를 조정하여 청색광을 줄이는 것이 좋습니다. 어두운 테마나 어두운 모드를 통해 일반적으로 밝은 조명이나 불규칙한 조명을 피하는 것도 도움이 됩니다.

AMOLED 화면의 어두운 모드 전원 절약

마지막으로 어두운 모드는 AMOLED 화면에서 많은 에너지를 절약하는 것으로 알려져 있습니다. YouTube와 같은 인기 Google 앱에 중점을 둔 Android 사례 연구에 따르면 전력 절감 효과가 최대 60%에 달할 수 있습니다. 아래 동영상에서 이러한 사례 연구와 앱별 전원 절약에 관해 자세히 알아보세요.

운영체제에서 어두운 모드 활성화

이제 어두운 모드가 많은 사용자에게 중요한 이유에 관한 배경을 살펴봤으므로 이를 지원하는 방법을 검토해 보겠습니다.

Android Q 어두운 모드 설정
Android Q 어두운 테마 설정

어두운 모드 또는 어두운 테마를 지원하는 운영체제에는 일반적으로 설정의 어딘가에 이를 활성화하는 옵션이 있습니다. macOS X에서는 시스템 환경설정의 일반 섹션에 있으며 모양이라고 합니다 (스크린샷). Windows 10에서는 색상 섹션에 있으며 색상 선택이라고 합니다 (스크린샷). Android Q의 경우 디스플레이에서 어두운 테마 전환 스위치 (스크린샷)로 찾을 수 있으며 iOS 13에서는 설정의 디스플레이 및 밝기 섹션에서 모양을 변경할 수 있습니다 (스크린샷).

prefers-color-scheme 미디어 쿼리

시작하기 전에 마지막으로 이론을 한 가지 더 설명하겠습니다. 미디어 쿼리를 사용하면 작성자가 렌더링되는 문서와 관계없이 사용자 에이전트 또는 디스플레이 기기의 값이나 기능을 테스트하고 쿼리할 수 있습니다. CSS @media 규칙에서 문서에 조건부로 스타일을 적용하는 데 사용되며 HTML 및 JavaScript와 같은 다른 다양한 컨텍스트와 언어에서도 사용됩니다. 미디어 쿼리 수준 5에서는 사이트에서 사용자가 콘텐츠를 표시하는 데 선호하는 방식을 감지하는 방법인 사용자 환경설정 미디어 기능을 도입합니다.

prefers-color-scheme 미디어 기능은 사용자가 페이지에서 밝은 색상 테마 또는 어두운 색상 테마를 사용하도록 요청했는지 감지하는 데 사용됩니다. 다음 값과 호환됩니다.

  • light: 사용자가 밝은 테마(밝은 배경에 어두운 텍스트)가 적용된 페이지를 선호한다고 시스템에 알린 것을 나타냅니다.
  • dark: 사용자가 어두운 테마(어두운 배경에 밝은 텍스트)가 적용된 페이지를 선호한다고 시스템에 알린 것을 나타냅니다.

어두운 모드 지원

브라우저에서 어두운 모드를 지원하는지 확인

어두운 모드는 미디어 쿼리를 통해 보고되므로 미디어 쿼리 prefers-color-scheme가 일치하는지 확인하여 현재 브라우저가 어두운 모드를 지원하는지 쉽게 확인할 수 있습니다. 값을 포함하지 않고 미디어 쿼리만 일치하는지 확인하는 방법에 유의하세요.

if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
  console.log('🎉 Dark mode is supported');
}

이 글을 작성하는 시점에서 prefers-color-scheme는 Chrome 및 Edge 버전 76, Firefox 버전 67, macOS의 Safari 버전 12.1, iOS의 Safari 버전 13부터 데스크톱과 모바일 (제공되는 경우)에서 모두 지원됩니다. 다른 모든 브라우저의 경우 지원 표를 사용할 수 있나요를 확인하세요.

요청 시 사용자의 환경설정 알아보기

Sec-CH-Prefers-Color-Scheme 클라이언트 힌트 헤더를 사용하면 사이트에서 요청 시 선택적으로 사용자의 색 구성표 환경설정을 가져올 수 있으므로 서버가 올바른 CSS를 인라인으로 삽입하여 잘못된 색상 테마가 표시되는 것을 방지할 수 있습니다.

어두운 모드 사용하기

마지막으로 어두운 모드 지원이 실제로 어떻게 표시되는지 살펴보겠습니다. Highlander와 마찬가지로 어두운 모드에서는 둘 중 하나만 선택할 수 있습니다. 어둡거나 밝을 수 있지만 둘 다 선택할 수는 없습니다. 이 문제를 언급하는 이유는 무엇인가요? 이 사실은 로드 전략에 영향을 미치기 때문입니다. 사용자가 현재 사용하지 않는 모드용 CSS를 중요한 렌더링 경로에서 강제로 다운로드하도록 해서는 안 됩니다. 따라서 로드 속도를 최적화하기 위해 다음 권장사항을 실제로 보여주는 예시 앱의 CSS를 세 부분으로 나누어 비중 낮은 CSS를 지연했습니다.

  • style.css: 사이트에서 전반적으로 사용되는 일반 규칙이 포함되어 있습니다.
  • 어두운 모드에 필요한 규칙만 포함된 dark.css
  • 밝은 모드에 필요한 규칙만 포함된 light.css

로드 전략

후자의 두 가이드라인인 light.cssdark.css<link media> 쿼리로 조건부로 로드됩니다. 처음에는 일부 브라우저에서 prefers-color-scheme를 지원하지 않습니다(위의 패턴을 사용하여 감지 가능). 이를 처리하기 위해 조건부로 삽입된 <link rel="stylesheet"> 요소를 통해 기본 light.css 파일을 로드하는 방식으로 동적으로 처리합니다(밝은 색상은 임의로 선택한 것이며 어두운 색상을 기본 대체 환경으로 만들 수도 있음). 스타일이 지정되지 않은 콘텐츠가 잠시 표시되는 것을 방지하기 위해 light.css가 로드될 때까지 페이지의 콘텐츠를 숨깁니다.

<script>
  // If `prefers-color-scheme` is not supported, fall back to light mode.
  // In this case, light.css will be downloaded with `highest` priority.
  if (window.matchMedia('(prefers-color-scheme: dark)').media === 'not all') {
    document.documentElement.style.display = 'none';
    document.head.insertAdjacentHTML(
      'beforeend',
      '<link rel="stylesheet" href="/light.css" onload="document.documentElement.style.display = \'\'">',
    );
  }
</script>
<!--
  Conditionally either load the light or the dark stylesheet. The matching file
  will be downloaded with `highest`, the non-matching file with `lowest`
  priority. If the browser doesn't support `prefers-color-scheme`, the media
  query is unknown and the files are downloaded with `lowest` priority (but
  above I already force `highest` priority for my default light experience).
-->
<link rel="stylesheet" href="/dark.css" media="(prefers-color-scheme: dark)" />
<link
  rel="stylesheet"
  href="/light.css"
  media="(prefers-color-scheme: light)"
/>
<!-- The main stylesheet -->
<link rel="stylesheet" href="/style.css" />

스타일시트 아키텍처

CSS 변수를 최대한 활용합니다. 이렇게 하면 일반 style.css가 일반이 될 수 있고 모든 밝은 모드 또는 어두운 모드 맞춤설정이 다른 두 파일 dark.csslight.css에서 이루어집니다. 아래에서 실제 스타일의 발췌 부분을 확인할 수 있습니다. 전체적인 아이디어를 전달하기에 충분합니다. 기본적으로 밝은 배경에 어두운 글꼴어두운 배경에 밝은 글꼴 기준 테마를 만드는 두 변수 -⁠-⁠color-⁠-⁠background-color를 선언합니다.

/* light.css: 👉 dark-on-light */
:root {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
}
/* dark.css: 👉 light-on-dark */
:root {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
}

그런 다음 style.css에서 body { … } 규칙에 이러한 변수를 사용합니다. :root CSS 의사 클래스(HTML에서 <html> 요소를 나타내고 특수성이 더 높다는 점을 제외하고 선택자 html와 동일한 선택자)에 정의되어 있으므로 아래로 계단식 적용되므로 전역 CSS 변수를 선언하는 데 사용할 수 있습니다.

/* style.css */
:root {
  color-scheme: light dark;
}

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

위의 코드 샘플에서 공백으로 구분된 값 light dark이 있는 속성 color-scheme를 확인했을 것입니다.

이렇게 하면 브라우저에 앱에서 지원하는 색상 테마를 알리고 사용자 에이전트 스타일시트의 특수 변형을 활성화할 수 있습니다. 이는 예를 들어 브라우저가 어두운 배경과 밝은 텍스트로 양식 필드를 렌더링하도록 하거나, 스크롤 막대를 조정하거나, 테마 인식 강조 표시 색상을 사용 설정하는 데 유용합니다. color-scheme의 정확한 세부정보는 CSS 색상 조정 모듈 수준 1에 지정되어 있습니다.

그 외의 모든 것은 내 사이트에서 중요한 항목에 관한 CSS 변수를 정의하는 문제입니다. 어두운 모드를 사용할 때 스타일을 의미론적으로 정리하면 큰 도움이 됩니다. 예를 들어 어두운 모드에서 '노란색'이 실제로 노란색이 아닐 수도 있고 그 반대의 경우도 있으므로 -⁠-⁠highlight-yellow 대신 -⁠-⁠accent-color 변수를 호출하는 것이 좋습니다. 다음은 예시에서 사용한 몇 가지 변수의 예입니다.

/* dark.css */
:root {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
  --link-color: rgb(0, 188, 212);
  --main-headline-color: rgb(233, 30, 99);
  --accent-background-color: rgb(0, 188, 212);
  --accent-color: rgb(5, 5, 5);
}
/* light.css */
:root {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
  --link-color: rgb(0, 0, 238);
  --main-headline-color: rgb(0, 0, 192);
  --accent-background-color: rgb(0, 0, 238);
  --accent-color: rgb(250, 250, 250);
}

전체 예

다음 Glitch 삽입에서 위의 개념을 실제로 구현한 전체 예시를 확인할 수 있습니다. 특정 운영체제 설정에서 어두운 모드를 전환해 보고 페이지가 어떻게 반응하는지 확인합니다.

로드 영향

이 예시를 실행하면 미디어 쿼리를 통해 dark.csslight.css를 로드하는 이유를 확인할 수 있습니다. 어두운 모드를 전환하고 페이지를 새로고침해 보세요. 현재 일치하지 않는 특정 스타일시트는 여전히 로드되지만 우선순위가 가장 낮으므로 현재 사이트에 필요한 리소스와 경쟁하지 않습니다.

밝은 모드에서 어두운 모드 CSS가 가장 낮은 우선순위로 로드되는 방식을 보여주는 네트워크 로드 다이어그램
밝은 모드의 사이트는 가장 낮은 우선순위로 어두운 모드 CSS를 로드합니다.
어두운 모드에서 밝은 모드 CSS가 가장 낮은 우선순위로 로드되는 방식을 보여주는 네트워크 로드 다이어그램
어두운 모드의 사이트는 가장 낮은 우선순위로 밝은 모드 CSS를 로드합니다.
기본 밝은 모드에서 어두운 모드 CSS가 가장 낮은 우선순위로 로드되는 방식을 보여주는 네트워크 로드 다이어그램
prefers-color-scheme를 지원하지 않는 브라우저의 기본 밝은 모드 사이트는 가장 낮은 우선순위로 어두운 모드 CSS를 로드합니다.

어두운 모드 변경에 반응

다른 미디어 쿼리 변경사항과 마찬가지로 어두운 모드 변경사항은 JavaScript를 통해 구독할 수 있습니다. 이를 사용하여 페이지의 favicon을 동적으로 변경하거나 Chrome의 URL 표시줄 색상을 결정하는 <meta name="theme-color">를 변경할 수 있습니다. 위의 전체 예시에서 이를 확인할 수 있습니다. 테마 색상과 파비콘 변경사항을 보려면 별도의 탭에서 데모를 엽니다.

const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
darkModeMediaQuery.addEventListener('change', (e) => {
  const darkModeOn = e.matches;
  console.log(`Dark mode is ${darkModeOn ? '🌒 on' : '☀️ off'}.`);
});

Chromium 93 및 Safari 15부터 meta 테마 색상 요소의 media 속성을 사용하여 미디어 쿼리를 기반으로 색상을 조정할 수 있습니다. 일치하는 첫 번째 항목이 선택됩니다. 예를 들어 밝은 모드에는 색상 하나를, 어두운 모드에는 다른 색상을 사용할 수 있습니다. 이 글을 작성하는 시점에서는 매니페스트에서 이를 정의할 수 없습니다. w3c/manifest#975 GitHub 문제를 참고하세요.

<meta
  name="theme-color"
  media="(prefers-color-scheme: light)"
  content="white"
/>
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />

어두운 모드 디버깅 및 테스트

DevTools에서 prefers-color-scheme 에뮬레이션

전체 운영체제의 색 구성표를 전환하면 매우 빨리 불편해질 수 있으므로 이제 Chrome DevTools를 사용하면 현재 표시된 탭에만 영향을 미치는 방식으로 사용자의 선호하는 색 구성표를 에뮬레이션할 수 있습니다. 명령어 메뉴를 열고 Rendering를 입력하기 시작하여 Show Rendering 명령어를 실행한 다음 CSS 미디어 기능 prefers-color-scheme 에뮬레이션 옵션을 변경합니다.

Chrome DevTools의 렌더링 탭에 있는 &#39;CSS 미디어 기능 prefers-color-scheme 에뮬레이션&#39; 옵션의 스크린샷

Puppeteer로 prefers-color-scheme 스크린샷 찍기

PuppeteerDevTools 프로토콜을 통해 Chrome 또는 Chromium을 제어하는 고급 API를 제공하는 Node.js 라이브러리입니다. dark-mode-screenshot를 사용하면 어두운 모드와 밝은 모드 모두에서 페이지의 스크린샷을 만들 수 있는 Puppeteer 스크립트를 제공합니다. 이 스크립트를 일회성으로 실행하거나 지속적 통합 (CI) 테스트 모음의 일부로 만들 수 있습니다.

npx dark-mode-screenshot --url https://googlechromelabs.github.io/dark-mode-toggle/demo/ --output screenshot --fullPage --pause 750

어두운 모드 권장사항

순백색 피하기

순백색을 사용하지 않는다는 작은 디테일을 눈치채셨을 수도 있습니다. 대신 주변의 어두운 콘텐츠에 비해 번쩍거리거나 번지는 현상을 방지하기 위해 약간 더 어두운 흰색을 선택합니다. rgb(250, 250, 250)와 같은 값이 좋습니다.

사진 이미지의 색상을 다시 지정하고 어둡게 처리

아래의 두 스크린샷을 비교해 보면 핵심 테마가 밝은 배경에 어두운 텍스트에서 어두운 배경에 밝은 텍스트로 변경되었을 뿐만 아니라 히어로 이미지도 약간 다르게 보입니다. 사용자 조사에 따르면 설문조사에 참여한 사용자의 대다수가 어두운 모드가 활성화된 경우 약간 덜 선명하고 밝은 이미지를 선호하는 것으로 나타났습니다. 저는 이를 재색상 지정이라고 합니다.

어두운 모드에서 히어로 이미지가 약간 어두워집니다.
어두운 모드에서 히어로 이미지가 약간 어두워졌습니다.
밝은 모드의 일반 히어로 이미지
밝은 모드의 일반 히어로 이미지

이미지에 CSS 필터를 적용하여 색상을 다시 지정할 수 있습니다. URL에 .svg가 없는 모든 이미지와 일치하는 CSS 선택기를 사용합니다. 벡터 그래픽 (아이콘)에 이미지 (사진)와 다른 색상 재지정을 적용할 수 있다는 아이디어입니다. 자세한 내용은 다음 단락을 참고하세요. 나중에 필터를 유연하게 변경할 수 있도록 CSS 변수를 다시 사용하는 방법에 주의하세요.

재색상 지정은 어두운 모드, 즉 dark.css가 활성화된 경우에만 필요하므로 light.css에는 상응하는 규칙이 없습니다.

/* dark.css */
--image-filter: grayscale(50%);

img:not([src*='.svg']) {
  filter: var(--image-filter);
}

JavaScript로 어두운 모드 재색상 지정 강도 맞춤설정

모든 사용자가 동일하지는 않으며 어두운 모드에 대한 요구사항도 다릅니다. 위에 설명된 재색상 지정 메서드를 따르면 회색조 강도를 JavaScript를 통해 변경할 수 있는 사용자 환경설정으로 쉽게 만들 수 있으며, 값을 0%로 설정하여 재색상 지정을 완전히 사용 중지할 수도 있습니다. document.documentElement는 문서의 루트 요소에 대한 참조를 제공합니다. 즉, :root CSS 의사 클래스로 참조할 수 있는 동일한 요소입니다.

const filter = 'grayscale(70%)';
document.documentElement.style.setProperty('--image-filter', value);

벡터 그래픽 및 아이콘 반전

벡터 그래픽의 경우(제 경우에는 <img> 요소를 통해 참조하는 아이콘으로 사용됨) 다른 색상 재지정 방법을 사용합니다. 연구에 따르면 사람들은 사진의 색상 반전을 좋아하지 않지만 대부분의 아이콘에는 색상 반전이 매우 효과적입니다. 다시 CSS 변수를 사용하여 일반 상태와 :hover 상태의 반전 양을 결정합니다.

어두운 모드에서는 아이콘이 반전됩니다.
어두운 모드에서 아이콘이 반전됩니다.
밝은 모드의 일반 아이콘
밝은 모드의 일반 아이콘

dark.css에서는 아이콘을 반전하고 light.css에서는 반전하지 않는 것을 다시 한번 확인하고, :hover가 두 경우에서 서로 다른 반전 강도를 사용하여 사용자가 선택한 모드에 따라 아이콘이 약간 더 어둡게 또는 약간 더 밝게 표시되는 것을 확인합니다.

/* dark.css */
--icon-filter: invert(100%);
--icon-filter_hover: invert(40%);

img[src*='.svg'] {
  filter: var(--icon-filter);
}
/* light.css */
--icon-filter_hover: invert(60%);
/* style.css */
img[src*='.svg']:hover {
  filter: var(--icon-filter_hover);
}

인라인 SVG에 currentColor 사용

인라인 SVG 이미지의 경우 반전 필터를 사용하는 대신 요소의 color 속성 값을 나타내는 currentColor CSS 키워드를 활용할 수 있습니다. 이렇게 하면 기본적으로 color 값을 수신하지 않는 속성에서 color 값을 사용할 수 있습니다. 편리하게도 currentColor가 SVG fill 또는 stroke 속성의 값으로 사용되면 대신 색상 속성의 상속된 값에서 값을 가져옵니다. 더 좋은 점은 <svg><use href="…"></svg>에도 작동하므로 별도의 리소스를 보유할 수 있고 currentColor는 여전히 컨텍스트에 적용됩니다. 이는 인라인 또는 <use href="…"> SVG에만 적용되며 이미지의 src로 참조되거나 CSS를 통해 참조되는 SVG에는 적용되지 않습니다. 아래 데모에서 적용된 모습을 확인할 수 있습니다.

<!-- Some inline SVG -->
<svg xmlns="http://www.w3.org/2000/svg"
    stroke="currentColor"
>
  […]
</svg>

모드 간 원활한 전환

colorbackground-color가 모두 애니메이션이 가능한 CSS 속성이므로 어두운 모드에서 밝은 모드로 전환하거나 그 반대로 전환할 때 원활하게 전환할 수 있습니다. 애니메이션을 만드는 것은 두 속성에 transition를 두 개 선언하는 것만큼 쉽습니다. 아래 예는 전반적인 개념을 보여줍니다. 데모에서 실시간으로 확인할 수 있습니다.

body {
  --duration: 0.5s;
  --timing: ease;

  color: var(--color);
  background-color: var(--background-color);

  transition: color var(--duration) var(--timing), background-color var(
        --duration
      ) var(--timing);
}

어두운 모드의 아트 디렉션

일반적으로 로드 성능상의 이유로 스타일시트의 인라인이 아닌 <link> 요소의 media 속성에서 prefers-color-scheme를 사용해야 하지만, HTML 코드에서 직접 인라인으로 prefers-color-scheme를 사용해야 하는 경우도 있습니다. 아트 디렉션이 바로 이러한 상황입니다. 웹에서 아트 디렉션은 페이지의 전반적인 시각적 노출과 시각적으로 소통하고, 분위기를 자극하고, 특징을 대비하며, 타겟층에 심리적으로 어필하는 방식을 다룹니다.

어두운 모드에서는 특정 모드에서 가장 적합한 이미지가 무엇인지, 이미지의 색상 재지정이 충분하지 않을 수 있는지 여부를 디자이너가 판단합니다. <picture> 요소와 함께 사용하면 표시할 이미지의 <source>media 속성에 종속시킬 수 있습니다. 아래 예에서는 어두운 모드의 경우 서반구를, 밝은 모드의 경우 동반구를, 환경설정이 지정되지 않은 경우에는 다른 모든 경우에 동반구를 기본값으로 표시합니다. 물론 이는 설명을 위한 예시일 뿐입니다. 기기에서 어두운 모드를 전환하여 차이점을 확인해 보세요.

<picture>
  <source srcset="western.webp" media="(prefers-color-scheme: dark)" />
  <source srcset="eastern.webp" media="(prefers-color-scheme: light)" />
  <img src="eastern.webp" />
</picture>

어두운 모드, 선택 해제 옵션 추가

위의 어두운 모드 사용 이유 섹션에서 언급했듯이 어두운 모드는 대부분의 사용자에게 미적 선택사항입니다. 따라서 일부 사용자는 운영체제 UI를 어둡게 설정하고 싶지만 웹페이지는 평소와 같이 보고 싶어 할 수 있습니다. 좋은 패턴은 처음에는 브라우저가 prefers-color-scheme를 통해 전송하는 신호를 따르되, 원하는 경우 사용자가 시스템 수준 설정을 재정의하도록 허용하는 것입니다.

<dark-mode-toggle> 맞춤 요소

물론 이 코드를 직접 만들 수도 있지만 이 용도로 제가 만든 바로 사용할 수 있는 맞춤 요소 (웹 구성요소)를 사용해도 됩니다. 이름은 <dark-mode-toggle>이며 완전히 맞춤설정할 수 있는 전환 버튼 (어두운 모드: 사용/사용 안 함) 또는 테마 전환 도구 (테마: 밝은/어두운)를 페이지에 추가합니다. 아래 데모에서는 이 요소가 작동하는 모습을 보여줍니다. 다른 의 모든 예시에도 🤫 조용히 슬쩍 넣어 두었습니다.

<dark-mode-toggle
  legend="Theme Switcher"
  appearance="switch"
  dark="Dark"
  light="Light"
  remember="Remember this"
></dark-mode-toggle>
밝은 모드의 dark-mode-toggle
<dark-mode-toggle> 밝은 모드
밝은 모드의 dark-mode-toggle
어두운 모드의 <dark-mode-toggle>

아래 데모에서 오른쪽 상단의 어두운 모드 컨트롤을 클릭하거나 탭해 보세요. 세 번째 및 네 번째 컨트롤의 체크박스를 선택하면 페이지를 새로고침해도 모드 선택이 어떻게 기억되는지 확인할 수 있습니다. 이렇게 하면 방문자가 운영체제를 어두운 모드로 유지하면서 사이트를 밝은 모드로 이용하거나 그 반대로 이용할 수 있습니다.

결론

어두운 모드를 사용하고 지원하는 것은 재미있으며 새로운 디자인 방향을 열어줍니다. 일부 방문자에게는 사이트를 처리할 수 없는 것과 만족스러운 사용자인 것의 차이가 될 수 있습니다. 몇 가지 함정이 있으며 신중한 테스트가 필요하지만 어두운 모드는 모든 사용자를 소중하게 생각한다는 것을 보여주는 좋은 기회입니다. 이 게시물에 언급된 권장사항과 <dark-mode-toggle> 맞춤 요소와 같은 도우미를 사용하면 멋진 어두운 모드 환경을 만들 수 있습니다. 트위터에서 제작한 콘텐츠와 이 게시물이 유용했는지, 개선을 위한 제안사항이 있는지 알려주세요. 읽어주셔서 감사합니다. 🌒

prefers-color-scheme 미디어 쿼리에 관한 리소스:

color-scheme 메타 태그 및 CSS 속성에 관한 리소스:

일반 어두운 모드 링크:

이 게시물의 배경 조사 도움말:

감사의 말씀

prefers-color-scheme 미디어 기능, color-scheme CSS 속성, 관련 메타 태그는 👏 룬 릴레스베인의 구현 작업입니다. 룬은 CSS 색상 조정 모듈 수준 1 사양의 공동 편집자이기도 합니다. 이 도움말을 꼼꼼하게 검토해 주신 루카시츠비루트님, 로완 메리우드님, 치라그 데사이님, 롭 도슨님께 감사드립니다. 로드 전략제이크 아치볼드의 아이디어입니다. Emilio Cobos Álvarez님이 올바른 prefers-color-scheme 감지 방법을 알려 주었습니다. 참조된 SVG 및 currentColor가 포함된 도움말은 티모시 해처님이 제공해 주셨습니다. 마지막으로 이 도움말의 권장사항을 수립하는 데 도움을 준 다양한 사용자 연구의 익명의 많은 참여자에게 감사의 인사를 전합니다. 네이선 앤더슨의 히어로 이미지