웹페이지 다크 모드 지원은 prefers-color-scheme
미디어 쿼리를 사용해서 적용할 수 있다. 각 해상도에 따라 미디어 쿼리를 적용하는 방식과 크게 다르지 않다.
.title {
color: #101010;
}
.desc {
background-color: darkorange;
}
@media (prefers-color-scheme: dark) {
.title {
color: #EFEFEF;
}
.desc {
background-color: peachpuff;
}
}
이제 해당 페이지는 다크 모드로 지정했다면 해당 스타일로 적용된다. CSS 프로퍼티로 정의하면 자료와 구조를 분리할 수 있어 좀 더 깔끔해진다.
:root {
--title-color: #101010;
--desc-color: darkorange;
}
@media (prefers-color-scheme: dark) {
:root {
--title-color: #EFEFEF;
--desc-color: peachpuff;
}
}
.title {
color: var(--title-color);
}
.desc {
background-color: var(--desc-color);
}
사용자가 시스템에서 설정한 대로 보이긴 하지만 웹페이지에서 직접 변경할 수 있도록 옵션을 제공할 수도 있다. localStorage
에 설정을 저장해서 다시 웹페이지에 접속할 때 마지막 설정을 불러올 수 있다.
:root {
--title-color: #101010;
--desc-color: darkorange;
}
@media (prefers-color-scheme: dark) {
:root {
--title-color: #EFEFEF;
--desc-color: peachpuff;
}
}
[data-theme="light"] {
--title-color: #101010;
--desc-color: darkorange;
}
[data-theme="dark"] {
--title-color: #EFEFEF;
--desc-color: peachpuff;
}
/* ... */
저장된 값이 있다면 페이지에 설정한다.
const theme = localStorage.getItem('theme');
if (theme) {
document.documentElement.setAttribute('data-theme', theme);
}
시스템 설정을 확인하기 위해서 window.matchMedia()
함수를 사용할 수 있다. CSS의 미디어 쿼리가 현재 페이지에 해당하는지 확인하는 기능을 제공한다.
function toggleTheme() {
// 저장된 값이 없다면 시스템 설정을 기준으로 함
const currentTheme = localStorage.getItem('theme')
|| (
window.matchMedia("(prefers-color-scheme: dark)").matches
? 'dark'
: 'light'
);
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
// 최상위 엘리먼트에 설정, 로컬 스토리지에 설정을 저장
document.documentElement.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
}
만약 미디어 쿼리의 결과를 동적으로 반영해야 하는 경우에는 window.matchMedia()
의 반환값인 MediaQueryList
에 이벤트 리스너를 추가할 수 있다.
const mql = window.matchMedia("(prefers-color-scheme: dark)");
mql.addEventListener((e) => {
if (e.matches) {
// 해당 미디어 쿼리가 참인 경우
} else {
// 해당 미디어 쿼리가 거짓인 경우
}
});