최근에 많이 사용되는 다크모드, 라이트모드를 구현해 보면서 처음 알게 된 내용을 정리해보려고 한다.
1. OS 설정에 맞춰 모드 변경하는 방법 : prefers-color-scheme
prefers-color-scheme 미디어 쿼리는 OS에서 설정된 라이트/다크 모드를 감지하여
자동으로 라이트, 다크 모드 스타일을 적용하는 기능이다.
일반식으로 쓰면 아래처럼 표현할 수 있다.
@media (prefers-color-scheme: 모드) {
/* 해당 모드에 적용할 스타일 */
}
다크모드 스타일 설정 예시
@media (prefers-color-scheme: dark) {
body {
background-color: var(--background-color);
color: var(--text-color);
}
}
라이트모드 스타일 설정 예시
@media (prefers-color-scheme: light) {
body {
background-color: var(--background-color);
color: var(--text-color);
}
}
웹 사이트 규모가 커지면 다크모드, 라이트모드 지원을 위한 스타일이 복잡해진다.
더 쉬운 모드 스타일을 위해 CSS 변수
를 사용할 수 있다.
:root {
--loading-indicator-color: #ff9d3f;
--loading-indicator-background: #efebe9;
--black: #1b1b1b;
--white: #fff3e0;
}
@media (prefers-color-scheme: dark) {
body {
background-color: var(--black);
color: var(--white);
}
}
@media (prefers-color-schemeL: light) {
body {
background-color: var(--white);
color: var(--black);
}
}
2. 웹 페이지 내 토글 버튼을 추가하여 변경하는 방법
다크모드를 설정할 수 있는 토글 버튼 또는 체크박스를 추가하여 웹 내부에서 자체적으로 제어할 수 있는 방법이다.
만들어 둔 다크모드 설정 체크박스에 클릭 이벤트를 추가하여 body.dataset
을 변경하는 방식으로 구현해봤다.
Html
<body data-theme="light-mode">
<label class="darkmode_checkbox">
<input type="checkbox" class="darkmode_input" />
<span class="darkmode_text">다크모드 여부</span>
</label>
</body>
HTML에서 data-*
형식의 속성은 개발자가 정의한 데이터를 저장하는 데 사용된다.
나는 테마를 저장해 주기 위해 data-theme
라는 값을 만들고, 기본 값으로 light-mode
를 설정하였다.
JavaScript
darkmode_input.addEventListener('click', (event) => {
if (event.target.checked) {
document.body.dataset.theme = 'dark-mode';
} else {
document.body.dataset.theme = 'light-mode';
}
});
다크모드 체크박스에 클릭 이벤트를 걸어둔다.
체크되었다면 다크모드를, 아니라면 라이트 모드를 설정한다.
data 값을 자바스크립트에서 사용하려면 dataset.*
형식으로 접근해야 한다.
CSS
body[data-theme='light-mode'] {
--background-color: #fff3e0;
--text-color: #1b1b1b;
--button-color: #ffe97d;
}
body[data-theme='dark-mode'] {
--background-color: #1b1b1b;
--text-color: #fff3e0;
--button-color: #ffe97d;
}
body {
background-color: var(--background-color);
color: var(--text-color);
}
이제 CSS에서 테마 값에 따른 변수를 설정하고 바디에 적용해 주면 끝!
3. 위 둘을 동시에 적용하려면?
1번, 2번을 동시에 사용할 때 OS 모드에 따라 변경도 되고, 웹 내부에서도 변경이 될 줄 알았다.
그런데.. 그렇게 되지 않았다!
웹 체크박스에 따른 설정이 아예 먹통이 되어버렸다.ㅠㅠ
그럼 어떻게 해야 할까?
1번의 css에서 설정한 미디어 쿼리를 제거하고, 자바스크립트에서 설정하는 방법으로 구현할 수 있었다.
const mediaQuery = '(prefers-color-scheme: dark)';
setTheme(window.matchMedia(mediaQuery)); // 초기화
window.matchMedia(mediaQuery).addEventListener('change', setTheme);
function setTheme(mediaQueryList) {
document.body.dataset.theme = mediaQueryList.matches ? 'dark-mode' : 'light-mode';
}
웹이 실행될 때 테마를 초기화 해준 다음, OS의 모드가 변경되면 dataset.theme
값도 변경되도록 수정해 주었다.
참고자료
'개발공부 > 웹' 카테고리의 다른 글
시맨틱 마크업, 왜 필요할까? (0) | 2023.01.28 |
---|---|
구글 폰트 내 웹 사이트에 적용하는 방법 (0) | 2023.01.26 |
[React] memo와 react hook (0) | 2022.04.23 |
React의 pureCompoent 특징 (0) | 2022.04.23 |
[React] Refs (0) | 2022.04.21 |