WEB/📘 HTML, CSS

[CSS] 해와 달이 뜨고 지는 다크모드 버튼 만들기

무딘붓 2024. 6. 18. 20:51

 

해와 달이 뜨고 지는 다크모드 버튼

 

다크모드가 대중화 되면서 여러 모양의 다크모드 버튼을 만나볼 수 있습니다.

이미 여러 디자인이 공개되어 있지만, 저는 조금 더 독특한 버튼을 만들어보고 싶었습니다.

 

이번 게시글에서는 위 이미지처럼 해와 달이 떠오르고 지는 애니메이션이 포함된 다크모드 버튼을 만드는 방법을 소개하겠습니다.

 

1. 다크모드 토글 버튼 만들기

 

<button class="dark-light-toggle" aria-hidden="true">🌜</button>
document.addEventListener("DOMContentLoaded", function () {
  const savedTheme = localStorage.getItem("color-theme") || "light";
  document.documentElement.setAttribute("color-theme", savedTheme);
});

const toggleButton = document.querySelector('.dark-light-toggle');

toggleButton.addEventListener('click', () => {      
  const currentTheme = document.documentElement.getAttribute("color-theme");
  const newTheme = currentTheme === "light" ? "dark" : "light";
  document.documentElement.setAttribute("color-theme", newTheme);
  localStorage.setItem("color-theme", newTheme);
});

 

우선 간단한 버튼을 하나 만들고, JavaScript 코드를 위와 같이 작성해 주었습니다.

 

다크모드는 `document.documentElement` (=`<html>` 태그)의 속성을 변경하는 방식으로 구현됩니다. `color-theme` 속성의 기본값을 “light”로 설정하고, 토글 버튼을 클릭할 때마다 “light”와 “dark” 사이를 전환하도록 했습니다. 이와 함께, 현재 모드를 localStorage에 저장하여 페이지 새로고침 후에도 설정이 유지되도록 했습니다.

 

추가로, 스크린 리더에서 다크모드 토글 버튼을 탐색하지 않도록 `aria-hidden` 속성을 `true`로 설정했습니다.

 

2. CSS로 색상 변경하기

:root[color-theme='light'] {
  --surface-default: #F2F0EE;
  --btn-default: #FFFFFF;
  --btn-svg-hover: #FFA500;
}

:root[color-theme='dark'] {
  --surface-default: #17171C;
  --btn-default: #23232B;
  --btn-svg-hover: gold;
}

 

`:root` 는 HTML의 최상위 요소인 `<html>` 태그를 의미합니다.

 

위에서 작성한 JavaScript 코드로 `<html>` 태그의 `color-theme` 속성을 변경했으므로, 이를 이용해 손쉽게 다크모드를 구현할 수 있습니다. 

 

속성 선택자를 이용해 `color-theme` 값이 “light”일 때와 “dark”일 때 적용할 색상도 CSS 변수로 정의했습니다.

 

body {
  background-color: var(--surface-default);
  transition: background-color 0.5s;
}

.dark-light-toggle {
  display: flex;
  justify-content: center;
  align-items: center;
  
  position: relative;
  width: 50px;
  height: 50px;
  background-color: var(--btn-default);
  border: none;
  border-radius: 10px;
  overflow: hidden;
  cursor: pointer;

  transition: background-color 0.5s;
}   

 

이제 CSS 변수를 참조해 배경색과 버튼 색상을 지정하면, `<html>` 태그의 `color-theme` 속성이 바뀔 때 웹 페이지의 색상이 자연스럽게 변경됩니다.

 

다크모드 토글 버튼을 누르면 웹 페이지 색상이 변합니다.

 

 

3. 토글 버튼 디자인하기

 

<button class="dark-light-toggle" aria-hidden="true">
  <div class="icon30 sun"> 
    <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#222222"><path d="M480-280q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM200-440H40v-80h160v80Zm720 0H760v-80h160v80ZM440-760v-160h80v160h-80Zm0 720v-160h80v160h-80ZM256-650l-101-97 57-59 96 100-52 56Zm492 496-97-101 53-55 101 97-57 59Zm-98-550 97-101 59 57-100 96-56-52ZM154-212l101-97 55 53-97 101-59-57Z"/></svg>
  </div>
  <div class="icon30 moon">      
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#FFFFFF"><path d="M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q14 0 27.5 1t26.5 3q-41 29-65.5 75.5T444-660q0 90 63 153t153 63q55 0 101-24.5t75-65.5q2 13 3 26.5t1 27.5q0 150-105 255T480-120Z"/></svg>
  </div>
</button>

 

이제 토글 버튼에 태양과 달 모양의 아이콘을 추가하겠습니다. 여기서 사용한 SVG는 구글 머터리얼 아이콘에서 가져왔습니다.

 

.icon30 {
  display: flex;
  justify-content: center;
  align-items: center;      
  width: 30px;
  height: 30px;  
  position: absolute;
}
.icon30>svg{
  transition: fill 0.5s, transform 0.5s ease;   
}

.sun {
  display: flex;
}
.moon {
  display: none;
}

:root[color-theme='dark'] .dark-light-toggle .sun {
  display: none;
}
:root[color-theme='dark'] .dark-light-toggle .moon {
  display: flex;
}

.dark-light-toggle:hover svg {
  fill: var(--btn-svg-hover);
  transform: scale(1.2);
}

 

CSS를 설정하여 아이콘을 가운데로 정렬하고, `:root[color-theme='dark']`를 이용해 태양과 달의 `display`를 조절합니다. 

 

추가로, 버튼에 마우스를 올렸을 때 아이콘이 커지고 색상이 바뀌는 효과를 주면 아래와 같이 동작합니다.

 

디자인 작업이 끝난 다크모드 토글 버튼

 


4. 해와 달이 뜨고 지는 애니메이션 추가하기

 

아직 전환 효과가 밋밋하기 때문에, 태양과 달이 움직이는 모션을 추가해 보겠습니다.

태양과 달이 서쪽에서 뜨고, 동쪽으로 지는 모습이 버튼 내에서 보이도록 애니메이션을 아래와 같이 작성해 줍니다.

 

.icon30 {
  ...
  transition: transform 0.5s ease-in-out;
}

.sun {
  animation: rise-animation 1s forwards;
  transform-origin: 50% 200%
}
.moon {
  animation: set-animation 1s forwards;
  transform-origin: 50% 200%;
}

[color-theme='dark'] .dark-light-toggle .sun {
  animation: set-animation 1s forwards;
}
[color-theme='dark'] .dark-light-toggle .moon {
  animation: rise-animation 1s forwards;
}

@keyframes rise-animation {
  from {
    transform: rotate(180deg);
  }
  to {
    transform: rotate(360deg);
  }
}
@keyframes set-animation {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(180deg);
  }
}

 

일출을 표현하는 `rise-animation`과 일몰을 표현하는 `set-animation`을 만들었습니다. 

 

`transform-origin`을 `50% 200%`로 설정해 회전축을 태양의 아래쪽으로 지정하면 해가 뜨고 지는 애니메이션을 자연스럽게 구현할 수 있습니다. 달에도 같은 애니메이션을 설정하면 목표로 했던 다크모드 토글 버튼이 완성됩니다.

완성된 결과와 전체 코드는 아래 codepen에서 확인할 수 있습니다.

 

 

See the Pen 다크모드 토글버튼 by AA (@vchgekmq-the-flexboxer) on CodePen.

'WEB > 📘 HTML, CSS' 카테고리의 다른 글

CSS를 이용하여 링크 뒤에 아이콘 넣기  (0) 2022.12.30