디자인 시스템 세우기 1 — 라이트·다크를 네 벌 적으면 그중 하나가 몰래 달라집니다
목업의 색 토큰 표가 여섯 벌 있었어요. 그 사이에서 이 문서 자신의 보라가, Aurora는 #7040D9라고 적어둔 주석 바로 아래에서 다른 보라로 그려지고 있었습니다.
디자인 시스템을 세우면서 배운 것들을 세 편으로 나눠 적어보려고 합니다. 셋 다 같은 질문에서 출발해요.
같아야 하는 값을 어떻게 진짜로 같게 유지하지?
- 색 — 라이트·다크를 한 벌로 적는 법 — 지금 이 글
- 치수 — “저쪽과 같은 크기”라는 주석은 아무것도 묶지 않는다
- 그래서 만들어진 시스템 전체 — Aurora Ledger
첫 편은 색입니다. 이야기는 좀 부끄러운 장면에서 시작해요.
디자인 시스템 목업을 열었다가 이상한 걸 봤거든요.
/* Aurora 는 #7040D9 */
--brand: #6F3DE0;
주석 바로 아래에서 다른 값이 그려지고 있었습니다.
이 문서는 디자인 시스템을 설명하는 문서예요. 그 문서 자신의 브랜드색이 자기가 설명하는 값과 달랐던 겁니다.
색 표가 여섯 벌 있었어요
세어보니 이랬습니다.
| 벌 | 언제 이기나 |
|---|---|
:root (라이트) | 기본 |
@media (prefers-color-scheme: dark) | 시스템이 다크일 때 |
[data-theme="dark"] | 사용자가 다크를 고를 때 |
[data-theme="light"] | 사용자가 라이트를 고를 때 |
.phone 스킨 × 3 | 목업 안의 폰 목업 |
같은 값의 표가 여섯 벌이었어요.
그중 뒤에 온 블록 하나가 옛 보라(#6F3DE0)를 들고 있었고,
CSS는 뒤에 온 것이 이기니까 그게 화면에 나왔습니다.
진짜 문제는 “고칠 자리가 몇 개인지 모르게 되는 것”이에요
같은 값을 여러 자리에 적으면 흔히 “그중 하나를 고치는 걸 잊는다”고 말하죠. 그런데 실제로 일어나는 일은 좀 다릅니다.
고칠 자리가 몇 개인지를 모르게 돼요.
#6F3DE0을 지우려고 검색하면 몇 개가 나올지 모릅니다.
전부 고쳤는지 확인할 방법도 없어요.
화면을 봐도 지금 보고 있는 테마만 보이고요.
그리고 이게 테마 블록의 고약한 점입니다.
라이트로 직접 골랐을 때만 틀린 값은, 시스템 다크로 개발하는 동안 영영 안 보입니다.
[data-theme="light"] 블록은 사용자가 토글을 눌러 라이트를 고를 때만 적용돼요.
시스템이 라이트여도 :root 기본값이 쓰이므로 이 블록은 안 탑니다.
개발자가 그 조합을 일부러 만들지 않으면 평생 안 보는 코드인 거죠.
light-dark()로 한 벌이 됐어요
CSS에 light-dark()가 있습니다. 값 하나에 라이트·다크 두 값을 같이 적어요.
:root {
color-scheme: light dark;
--token-bg: light-dark(#F8F6FC, #110D19);
--token-text: light-dark(#21182D, #FAF7FF);
--token-primary: light-dark(#7040D9, #986CF4);
}
어느 쪽을 쓸지는 그 요소의 color-scheme이 정합니다.
그러니 테마를 직접 고르는 자리는 이 한 줄이면 끝이에요.
:root[data-theme="dark"] { color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }
미디어 쿼리도 없고, 특정도 싸움도 없습니다. 표는 한 벌이에요.
짧은 이름이 필요하면 가리키게 둡니다
화면 안에서 --token-bg가 길면 짧은 이름을 두고 싶어져요.
그때 값을 옮겨 적으면 다시 두 벌이 됩니다.
/* ✗ 두 벌이 됩니다 */
--bg: #F8F6FC;
/* ○ 가리킵니다 */
--bg: var(--token-bg);
color-scheme의 덤이 생각보다 커요
color-scheme은 “어느 값을 고를까”만 정하는 게 아닙니다.
브라우저가 그리는 것들의 색이 따라와요.
- 스크롤바
- 폼 컨트롤 (
<input>,<select>, 체크박스…) - 첫 캔버스(페이지 배경이 칠해지기 전의 바탕)
이 선언을 빼면 브라우저는 페이지가 라이트라고 믿습니다. 그래서 공들여 만든 어두운 판 옆에 은색 스크롤바를 세워요.
그건 “다크를 지원한다”가 아니라 “다크를 잊었다”로 읽힙니다.
주의할 게 하나 있어요.
이 값은 테마를 stamp하는 루트 요소에 얹어야 합니다.
body에만 걸면 뷰포트 스크롤바는 따라오지 않아요. 캔버스는 루트의 것을 보거든요.
브라우저 지원은 이제 문제가 아니에요
| 지원 시작 | |
|---|---|
| Chrome | 123 |
| Safari | 17.5 |
| Firefox | 120 |
이번 작업에서 정한 기준
- 색은
light-dark()한 줄로 적습니다. - 짧은 이름이 필요하면 가리키게 두지 옮겨 적지 않아요.
- 테마를 직접 고르는 자리는
color-scheme만 못 박습니다. color-scheme을 루트에 선언해요. 스크롤바와 폼 컨트롤이 딸려 옵니다.
한 벌은 한 번만 적습니다. 두 벌이 되는 순간, 둘이 언제 달라졌는지 아무도 모르게 되니까요.
결국 바꾼 것
이번 글은 색이 여러 벌이 된 이야기였어요. 그런데 같은 병이 색에서만 생기는 건 아니더라고요.
다음 글은 같은 병을 치수에서 본 이야기입니다. 그리고 이번엔 값을 묶어주던 게 CSS 블록도 아니고, 그냥 주석 한 줄이었어요.