loading

github.io 다크모드/라이트모드 (테마 밝기 조절) 만들기


Blog theme, 서버 관리

Published on December 10, 2022 by JunYoung

web designer blog github

7 min READ

테마 바꾸기 기능

밤에 핸드폰을 켜고 블로그에 들어왔다. 방에 불은 끈 상태였는데, 본인 블로그는 다크 모드를 지원하지 않는 바람에 눈뽕을 당해버렸다.

그래서 눈 건강을 위해 다크 모드를 도입하기로 했다. 대강 생각한 레이아웃은 다음과 같다.

이렇게 토글 스위치를 놓고 왼쪽으로 놓으면(“OFF” 상태) 라이트 모드가 되고 오른쪽으로 놓으면(“ON” 상태) 다크 모드가 되는 것이다. 사실 테마에 따라서 이미 css 파일이 있는 경우도 있으나 본인은 그렇지 않기 때문에 다음과 같은 방법을 사용했다.

CSS file 새로 만들기

보통 대부분 테마에서 html에 적용할 css를 head.html에서 가져온다. 어떤 구조로 되어있냐면,

이런 식이다. 그래서 해당 css 파일을 그대로 쓰면 기존처럼 라이트 모드가 나오기 때문에 비슷하지만 dark mode 테마로 적용할 수 있게끔 색상이나 세부 내용을 조절해줘야한다.
그래서 본인은 style_dark.css 파일을 새로 만들었다. 그리고 내부에서 어떤 내용을 조절해야하는지는,

로컬로 열어놓은 페이지에 ‘F12’를 눌러 스크립트창을 실행시킨 뒤, 창의 좌측 상단에 있는 네모+화살표(파랗게 표시된 부분)을 누르고 홈페이지 창 위에 가져다대면 해당 소스가 어디서부터 온 애인지 확인할 수 있다.
예를 들어 위의 예시를 보면 속성은 “h1”인 “title”이라는 것을 확인할 수 있다. 실제로 코드를 슥 보다보면 title을 금방 찾을 수 있는데, 이걸 소스코드에 적용하지 않고 먼저 웹에서 일시적으로 확인한 다음 고치고 싶다면 F12 창에서 소스를 고쳐봐도 된다. 근데 그냥 일단 소스에다가 바로 적용한다고 가정하고 진행하겠다.

이런 식으로 바꾸게 되면, 해당 영역에 배경이 생기는 걸 확인할 수 있다.

물론 소스 코드를 웹 상에서 시각화해서 볼 수도 있다.

이런 식으로 모든 부분들 색상을 따로 설정해주었고, 결과물은 다음과 같다.



등등 여러 부분에 다 적용했다. 특히 블로그, 포스트 등등에는 각 형식마다 색을 지정해주었다. 사실 이 부분이 가장 오래 걸렸는데, 색상 하나하나 Id를 찾아서 관련 내용들을 직접 적용하면서 확인해야했기에 미적인 감각도 필요했고 머리도 많이 썼다.

_config.yml에 다크모드 토글 옵션 넣기

다크모드 토글 기능을 사용할 때 css를 두 개 사용하게 되므로 해당 기능이 추가가 되었음을 head 파일에 추가해야했다. 그러면서 해당 옵션에 대한 부분도 yml 파일에서 value 값으로 읽어올 수 있게끔 해주기 위해 다음과 같이 넣었다.

darkmode_switch: true

head.html 고치기

그리고 앞서 봤던 head.html을 다음과 같이 수정하였다.

토글 버튼 넣기

이제는 다크 모드를 껐다가 켤 수 있는 버튼을 생성하는 코드를 설명하도록 하겠다. navigation bar 옆에 넣어서 바로 사용할 수 있게끔 하였다.

_sass/toggle.scss

_sass/toggle.scss로 토글용 스타일을 지정해주고,

.mh_toogle {
    display: none;
    + .mh_toggle_btn {
        margin-top: 0.6em;
        margin-left: 1em;
        margin-bottom: 0.6em;
        box-sizing: border-box;
        outline: 0;
        display: block;
        width: 4em;
        height: 2.0em;
        position: relative;
        cursor: pointer;
        user-select: none;
        border-radius: 1.5em;
        padding: 2px;
        transition: all 0.4s ease;
        font-size: 1em;

        &:after {
            position: relative;
            display: flex;
            justify-content: center;
            align-items: center;
            width: 50%;
            height: 100%;
            border-radius: 50%;
            transition: all 0.4s ease;
            color: gray;
            background: white;
        }

        background: gray;
        &:after {
            left: 0;
            content: "brightness_7";
        }
    }

    &:checked + .mh_toggle_btn {
        background: rgb(0, 0, 0);
        &:after {
            left: 50%;
            content: "brightness_4";
        }
    }
}

커스텀한 css 파일 오버라이딩용 파일에서 임포트를 해준다.

_sass/customOverride.scss

@import "./toggle.scss";

_sass/customImport.scss

/* font */
@import url('https://fonts.googleapis.com/css?family=Nanum+Gothic');
@import url('https://fonts.googleapis.com/icon?family=Material+Icons+Sharp');

_sass/main.scss, _sass/main_dark.scss

그리고 위의 내용들을 main.scss와 main_dark.scss에 모두 import 해준다. 두 scss는 내 테마에 맞게끔 생성한 것이므로 다른 테마에서는 다를 수도 있다.

@charset "utf-8";
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
@import url('https://cdn.jsdelivr.net/npm/bulma@0.8.2/css/bulma.min.css');
@import "customImport.scss";
@import "customOverride.scss";

맨 윗부분에 위와 같이 추가. 이제 토글을 html에 정의해주면 된다.
토글 버튼은 navigation이 보이는 상황에서 항상 등장해야하므로, navbar.html 파일을 수정하기로 하였다.

_includes/toggle.html

<input id="darkmode_switch" class="mh_toogle" type="checkbox">
<label for="darkmode_switch" class="material-icons-sharp mh_toggle_btn"></label>

이처럼 토글 스위치에 대한 내용들을 입력해주고,

네비게이션 옆에 바로 위치시켜준다. 이렇게 되면 화면 상단에 다음과 같이 뜬다. 각자의 웹 상황에 맞게 margin을 조절하면 된다.

토글 자바스크립트

이제 스크립트를 작성해서, 스위치의 상황에 맞게 스타일이 적용될 수 있게 할 것이다. 스크립트는 간단하게 navbar 아래쪽에 적어주었다.

<script>
    /* 스타일 파일들 */
    const defaultTheme = [...document.styleSheets].find(style => /(style.css)$/.test(style.href));
    const darkTheme = [...document.styleSheets].find(style => /(style_dark.css)$/.test(style.href));

    /* 스위치, 현재 테마 상태 불러오기 */
    let mode = document.getElementById("darkmode_switch");
    const current = localStorage.theme;

    /* 기존 상태에 따라 스위치 체크해주기 */
    mode.checked = current === 'dark';

    /* 체크된 거에 따라서 스타일 지정해주기 */
    darkTheme.disabled = mode.checked !== true;
    defaultTheme.disabled = mode.checked === true;

    mode.addEventListener('click', function(){
        localStorage.theme = mode.checked ? 'dark' : 'light';
        darkTheme.disabled = mode.checked !== true;
        defaultTheme.disabled = mode.checked === true;
    });

</script>

대충 내용을 설명하자면 스타일 파일들을 가져와서 const 상수로 놓는다. 그리고 기존 스위치 상태를 확인하기 위해 토글 스위치를 getId로 가져오고 localStorage의 theme 값을 불러온다.
만약 기존 상태가 dark 모드였다면 다크 모드를, 그게 아니라면 라이트 모드를 스위치에 적용한다. 이걸 안하면 홈페이지에서 이동할 때마다 테마가 초기화된다.
그리고 각 상태에 따라서 상수로 가져온 스타일 파일들을 disable시킨다. 이렇게 하는 이유는 직접적으로 html에서 스크립트 value를 참조하면 계층 구조가 애매해질 것 같아서 그랬다. 암튼 다크 모드에서는 darkTheme 파일을 사용하게 하고 반대의 경우에는 디폴트 파일을 사용하게 한다.
그리고 네비게이션에서 스위치를 누를 때마다 localStorage의 변수 theme을 바꿔주고, 스타일의 즉시 변환을 위해 theme disable 기능도 똑같이 적용해준다. 해당 스크립트까지 적용된 최종 완성본은 다음과 같다.

다음에는 utterance도 다크테마를 적용해봐야겠다.

A n o t h e r p o s t i n c a t e g o r y