hexo+ icarus 다크모드 구현하기
나는 다크모드를 아주 애용한다.
다크모드를 적용하며 유익한 경험이여서 글로 작성해두려고 한다.
hexo + icarus 작동원리
우선 hexo + icarus의 원리부터 알아야한다.
아래에 작성할 모든 디렉터리는 hexo루트 폴더 기준이다.
루드 디렉토리의 내부 파일을 수정한다.
그 후 정적파일인 public 폴더를 생성하고 배포하면 사이트에 반영되는 구조이다.
1 | hexo generate --deploy |
커스텀 디자인을 하기 위해선 이 ./themes 폴더를 수정해야한다.
버튼 만들기
./themes/icarus/layout/common 폴더엔 icarus의 여러 요소들의 jsx파일이 작성되어있다.
hexo\themes\icarus\layout\common\navbar.jsx파일에서 검색버튼 옆에 버튼을 만들었다.
1 | <button type="button" id="changeModeButton" class="navbar-item" /> |
버튼을 커스텀하기
./themes/icarus/include/style 폴더엔 여러 css들이 작성되어있다.
확장자가 styl인데 기존에 작성된 파일을 보니 들여쓰기로 depth를 관리하는 듯 했다.
그리고 이 파일들은 ./themes/source/css/style.styl에서 모두 import되고 이를 빌드하여 ./public/css에 하나의 css파일을 생성한다.
./themes/icarus/include/style/navbar.styl 파일에 다음과 같은 내용을 추가하였다.
1 | #changeModeButton { |
버튼에 로직 추가하기
./themes/source/js 폴더엔 여러 js파일들이 있다.
이는 ./themes/icarus/layout/common/scripts.js에서 한 번에 모아서 ./public/index.js에 작성된다.
여기에 다크모드 버튼 관련 파일을 작성하였다.
페이지에 접속 시 로컬스토리지를 확인하고 darkMode가 true일경우 html의 body에 darkMode 태그를 추가하고 버튼의 모양을 달 모양으로 해주었다.
값이 존재하지 않을경우 버튼의 모양을 해 모양으로 해주었다. 기본 값은 다크모드의 미적용이기 때문에 따로 처리를 해주진 않았다.
그리고 버튼에 이벤트를 등록해주었다.
1 | const darkModeButton = document.querySelector("#changeModeButton"); |
그리고 ./themes/icarus/layout/common/scripts.js에 아래 내용을 추가해주었다.
정확히 어떤 구조인지는 모르지만 main.js가 이런 식으로 작성되어 있길래 똑같이 적었다.
defer는 script로딩시 버튼이 없으면 안되기 때문에 추가해주었다.
1 | <script src={url_for("/js/darkmode.js")} defer></script> |
다크모드 css 추가하기
다음으로 darkmode.styl 파일을 작성해주었다.
처음 보는 확장자명이기도 했고 ./themes/include/style에 작성할지 ./themes/source/css에 작성할지 고민되었다.
고민끝에 include폴더는 컴포넌트마다의 css를 작성하는 느낌이 강해서 ./themes/source/css/darkmode.styl에 작성하였다.
css는 개발자 도구를 여러 하나하나 클래스명을 확인하며 적어주었다.
빌드과정에서 압축될 것이여서 하나씩 풀어 적었다.
1 | body.darkMode |
그리고 ./themes/source/css/style.styl에 import 해주었다.
1 | @import './darkmode.styl' |
정리
전체적인 로직은 다음과 같다.
- body.darkMode의 하위 태그들에 적용이 되도록 여러 css를 작성해둔다.
- 첫 접속시에 로컬스토리지에 darkMode 관련 값이 저장되어있는지 확인하고 알맞은 처리를 해준다. 새로고침시에 상태가 유지되게 하기 위함이다.
- 버튼 클릭시 다크모드가 적용되도록 이벤트를 추가해준다.(body태그에 darkMode 클래스를 toggle하도록)
완성본
다크모드가 적용될 경우 적용되지 않을경우의 버튼이 다르고 글자 색과 배경 색도 다르다.
느낀 점
- styl 확장자 파일을 작성해보았다.
- Stylus CSS파일이라고 하는데, 작성해보니 의외로 굉장히 편하였다.
- REACT가 아닌 jsx로 작성되어 이러한 파일들을 중앙에서 제어하여 빌드시 html을 만드는 과정에 대한 이해가 늘었다.
- jsx문법을 이용하여 컴포넌트 단위로 파일을 작성하고 관리하는 것이 얼마나 가독성이 좋은지 다시 한 번 느꼈다.
- 역시 다크모드가 눈이 편하다
- 다크모드가 최고다 ㅠ
아쉬운 점
- 구현을 하고 보니 코드블록이나 위젯에는 다크모드가 적용이 안 되었다.
- 이것도 개발자 도구를 이용하여 css를 까보고 수정해야겠다.
- 모바일에서 레이아웃이 아쉽다.
- 버튼을 추가하다보니 상단바에 스크롤바가 생겼다.
- 이것도 수정해보아야겠다. 레이아웃에 손을 대거나 전체적으로 크기를 줄이는 방향으로 갈 것 같다.
- 정신없이 작업하고 복기하며 메모하다보니 빠진 부분이 있을까봐 걱정된다.
- 다음부턴 간략한 개요든지 사진을 틈틈히 찍어두어야겠다 ㅠ
+++ 수정
다크모드를 끄고 게시글에 접근시 다크모드가 적용되는 버그가 있었다.
로컬스토리지에 데이터가 string으로 저장되는데 if(data)의 형태로 확인해서 발생한 버그였다.
1 | const loadDarkModeData = () => { |
위 부분을 다음과 같이 변경하였다.
1 | const loadDarkModeData = () => { |