홈 › 웹 제작
다크모드 제대로 만들기: 선택 기억, 기기 설정 따르기, 깜빡임 막기
처음 만든 다크모드 버튼은 누르면 색이 바뀌었지만, 새로고침하면 다시 밝은 화면으로 돌아갔습니다. 실제로 쓸 만한 다크모드가 되려면 세 가지를 더해야 했습니다.
기본 원리: 색을 변수로 모아 둔다
색을 곳곳에 직접 적지 않고 CSS 변수로 모아 두면, html에 dark라는 이름표 하나를 붙였다 떼는 것만으로 사이트 전체 색이 바뀝니다.
:root {
--bg: #ffffff;
--text: #1f2937;
}
html.dark {
--bg: #111827;
--text: #f3f4f6;
}
body {
background: var(--bg);
color: var(--text);
transition: background 0.3s, color 0.3s; /* 부드럽게 바뀌기 */
}
1. 고른 모드를 기억하기
브라우저에는 사이트별로 작은 값을 저장하는 localStorage가 있습니다. 버튼을 누를 때 고른 모드를 저장해 두면 다음에 와도 유지됩니다.
modeBtn.addEventListener("click", () => {
const isDark = document.documentElement.classList.toggle("dark");
try { localStorage.setItem("theme", isDark ? "dark" : "light"); } catch (e) {}
updateModeBtn();
});
try로 감싼 이유는 사생활 보호 모드 같은 환경에서 저장이 막혀 있으면 오류가 나기 때문입니다. 저장이 안 되더라도 버튼은 동작해야 합니다.
2. 처음 온 사람은 기기 설정을 따르기
휴대폰을 다크모드로 쓰는 사람이 처음 들어왔을 때 하얀 화면이 뜨면 눈이 부십니다. prefers-color-scheme으로 기기 설정을 읽어, 저장된 선택이 없을 때만 기기 설정을 따르게 했습니다.
3. 깜빡임 막기
모드 적용 코드를 페이지 맨 아래에 두면, 밝은 화면이 잠깐 그려졌다가 어두워지는 깜빡임이 생깁니다. 그래서 모드를 정하는 짧은 코드를 <head> 안, 화면이 그려지기 전에 실행되도록 옮겼습니다.
<script>
(function () {
let saved = null;
try { saved = localStorage.getItem("theme"); } catch (e) {}
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
if (saved === "dark" || (!saved && prefersDark)) {
document.documentElement.classList.add("dark");
}
})();
</script>
이름표를 body가 아니라 html에 붙이는 이유도 여기에 있습니다. <head>가 실행되는 순간에는 아직 body가 만들어지지 않았기 때문입니다.
함께 챙길 것: 바깥에서 불러온 화면
댓글 창처럼 다른 서비스가 그려 주는 영역은 내 CSS 변수를 따르지 않습니다. 이 사이트의 Disqus 댓글은 모드를 바꿀 때 댓글 창을 다시 불러오도록 처리했습니다. 자세한 내용은 정적 사이트에 댓글 달기에 정리했습니다.
댓글