Dark mode palette

다크모드 팔레트

A dark theme isn’t just inverted colors — the core trick is that surfaces get lighter, not darker, the higher they sit above the base layer.

Also known as: Dark theme다크 테마
···
html
<div class="wrap">
  <div class="stage" id="stage">
    <div class="row">
      <div class="lvl" id="l0">Surface</div>
      <div class="lvl" id="l1">+1</div>
      <div class="lvl" id="l2">+2</div>
    </div>
  </div>
  <button class="toggle" id="toggle"><span id="tglText">Dark</span></button>
</div>
css
.wrap{width:min(440px,92%);display:grid;gap:clamp(10px,2.6vmin,16px);justify-items:center}
.stage{width:100%;border-radius:18px;padding:clamp(12px,3.4vmin,20px);transition:background .5s}
.row{display:flex;gap:clamp(8px,2.6vmin,16px);justify-content:center}
.lvl{flex:1;max-width:120px;aspect-ratio:1;border-radius:12px;display:grid;place-items:center;text-align:center;
  font:700 clamp(9px,2.6vmin,12px)/1 ui-monospace,monospace;border:1px solid transparent;
  transition:background .5s,box-shadow .5s,color .5s,border-color .5s}
.toggle{border:1px solid var(--line);background:var(--surface);color:var(--fg);border-radius:999px;padding:8px 18px;font:700 clamp(10px,2.6vmin,12px)/1 system-ui;cursor:pointer}
js
let isDark = false;
const stage = document.getElementById('stage'), l0 = document.getElementById('l0'), l1 = document.getElementById('l1'), l2 = document.getElementById('l2');
const toggle = document.getElementById('toggle'), tglText = document.getElementById('tglText');
const HUE = 230;
function hsl(h, s, l) { return 'hsl(' + h + ', ' + s + '%, ' + l + '%)'; }

function render() {
  if (isDark) {
    stage.style.background = hsl(HUE, 22, 9);
    l0.style.background = hsl(HUE, 14, 14); l0.style.borderColor = 'transparent'; l0.style.boxShadow = 'none'; l0.style.color = '#f4f4f6';
    l1.style.background = hsl(HUE, 14, 20); l1.style.borderColor = 'transparent'; l1.style.boxShadow = '0 6px 16px rgba(0,0,0,.35)'; l1.style.color = '#f4f4f6';
    l2.style.background = hsl(HUE, 14, 27); l2.style.borderColor = 'transparent'; l2.style.boxShadow = '0 10px 24px rgba(0,0,0,.45)'; l2.style.color = '#f4f4f6';
  } else {
    stage.style.background = hsl(HUE, 30, 94);
    l0.style.background = '#ffffff'; l0.style.borderColor = 'var(--line)'; l0.style.boxShadow = 'none'; l0.style.color = '#15151a';
    l1.style.background = '#ffffff'; l1.style.borderColor = 'var(--line)'; l1.style.boxShadow = '0 6px 16px rgba(0,0,0,.10)'; l1.style.color = '#15151a';
    l2.style.background = '#ffffff'; l2.style.borderColor = 'var(--line)'; l2.style.boxShadow = '0 10px 24px rgba(0,0,0,.16)'; l2.style.color = '#15151a';
  }
  tglText.textContent = isDark ? 'Dark' : 'Light';
}
function flip() { isDark = !isDark; render(); }
render();
toggle.addEventListener('click', e => { e.stopPropagation(); flip(); });
setInterval(flip, 2600);

In light mode, elevated surfaces — cards, modals — read through shadow. Shadows barely register on a dark background, though. That's why systems like Material Design express hierarchy in dark mode by mixing a bit more white into a surface the higher its elevation — elevation 0 is darkest, and each level up gets a little lighter.

Dark themes also do better avoiding pure black (#000) and pure white text. Contrast that strong causes glare and halation, especially with thin fonts — a background near #121212 and text lightness just short of full white both help.

Brand colors usually need lower saturation and higher lightness on a dark background to stay legible without vibrating — dropping in the exact light-mode color almost always reads as either too loud or lost in the background.

When to use

Don’t auto-generate dark mode by inverting colors — design lightness per surface level on purpose.