5️⃣
JavaScript 20 Projects - 5 Light Dark Mode
前言
這系列是課程 JavaScript Web Projects: 20 Projects to Build Your Portfolio 的筆記,學習利用 Javascript 做出各種互動網站。
以下是這系列的文章:
Number | Name |
---|---|
Project 1 | Quote Generator |
Project 2 | Infinity Scroll |
Project 3 | Picture In Picture |
Project 4 | Joke Teller |
Project 5 | Light Dark Mode |
目標
實作 Light Dark Mode。
下面是這次要實作的畫面。範例的連結。
準備資源
HTML
-
fontawesome
- 可以挑選需要的 Icon。
-
unDraw
- 挑選圖片,這片可以選兩種顏色來當成 light 跟 dark 模式的圖片。
CSS
-
Hero Patterns
- 用來當背景圖案。
-
How TO - Toggle Switch
- 用來設定切換模式。
建立 HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Light/Dark Mode</title>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.10.2/css/all.min.css"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<header class="headerBar">
<!-- Navigation -->
<nav class="nav">
<a href="#home">HOME</a>
<a href="#about">ABOUT</a>
<a href="#projects">PROJECTS</a>
<a href="#contact">CONTACT</a>
</nav>
<!-- Dark Mode Switch -->
<div class="theme-switch-wrapper">
<span id="toggle-icon">
<span class="toggle-text">Light Mode</span>
<i class="fas fa-sun"></i>
</span>
<label class="theme-switch">
<input type="checkbox" />
<div class="slider round"></div>
</label>
</div>
</header>
<!-- Main Section -->
<section id="home">
<div class="title-group">
<h1>Discover story-worthy<br />travel moments</h1>
<h2>Best in travel !</h2>
<img
src="img/undraw_aircraft_re_light.svg"
alt="picture"
class="picture"
id="picture"
/>
</div>
</section>
<script src="script.js"></script>
</body>
</html>
建立 CSS
Using CSS custom properties (variables)
這邊介紹一個好用的 CSS 用法,可以用來設定一個網頁的色彩規劃。
可以利用double hyphen (--
) 來宣告一個 property,並給他你所要定義的value。
比如這邊在 root 定義主要的背景顏色,那在之後會用到這背景色的地方,就可以利用 var(—property)
的方式直接把在 root 定義好的顏色拿來用了。
:root {
--main-bg-color: brown;
}
element {
background-color: var(--main-bg-color);
}
以下是這次設定的顏色提供參考。
:root {
--primary-color: #43eac1;
--secondary-color: #1b9999;
--on-primary: rgb(250, 250, 250);
--on-background: rgb(66, 66, 66);
--on-background-alt: rgba(66, 66, 66, 0.7);
--background: rgb(255, 255, 255);
--box-shadow: 0 5px 20px 1px rgba(0, 0, 0, 0.5);
}
[data-theme="dark"] {
--primary-color: #6c63ff;
--secondary-color: #03dac5;
--on-primary: #000;
--on-background: rgba(255, 255, 255, 0.9);
--on-background-alt: rgba(255, 255, 255, 0.7);
--background: #121212;
}
思考 javascript 所需要的動作
- 如何切換兩個模式?
- 怎麼設定切換顏色?
動作解讀
如何切換兩個模式?
- 先利用 DOM 來控制 toggle 元素。
- 設定 function
switchTheme()
,確認 toggle checked 的狀態來設定lightMode()
/darkMode()
。- 利用 documentElement property 來
setAttribute()
。 -
"data-theme"
的部分是 Key ,"dark"
的部分是 value 。
- 利用 documentElement property 來
- 設定 Event Listener 。
const toggleSwitch = document.querySelector('input[type="checkbox"]');
// Switch Theme Dynamically
function switchTheme(event) {
if (event.target.checked) {
document.documentElement.setAttribute("data-theme", "dark");
darkMode();
} else {
document.documentElement.setAttribute("data-theme", "light");
lightMode();
}
}
// Event Listener
toggleSwitch.addEventListener("change", switchTheme);
怎麼設定切換顏色?
- 利用 DOM 來控制 Icon 跟 image 元素。
- 這裡示範在
lightMode()
/darkMode()
分別設定要替換的圖片、文字與 class (用來替換Icon)。
const toggleIcon = document.getElementById("toggle-icon");
const image = document.getElementById("picture");
// Dark Mode Styles
function darkMode() {
image.src = `img/undraw_aircraft_re_dark.svg`;
toggleIcon.children[0].textContent = "Dark Mode";
toggleIcon.children[1].classList.replace("fa-sun", "fa-moon");
}
// Light Mode Styles
function lightMode() {
image.src = `img/undraw_aircraft_re_light.svg`;
toggleIcon.children[0].textContent = "Light Mode";
toggleIcon.children[1].classList.replace("fa-moon", "fa-sun");
}
// Event Listener
toggleSwitch.addEventListener("change", switchTheme);
用 LocalStorage 來存使用者資料
可以 LocalStorage 來儲存資料,當你關掉瀏覽器再次開啟時,他會以上次關掉時所記住的模式來開啟。詳細可以看Window: localStorage property 。
- 要先新增在 LocalStorage 的Key,所以在
switchTheme()
分別設定theme ,並可以在 Develop Tool 的Application 中看到新增的 Key 以及 value 。localStorage.setItem("theme", "dark");
localStorage.setItem("theme", “light”);
- 接下來就是要設定當瀏覽器重新開啟時,要確認當前的模式是什麼?若有值的話,接著就設定模式相關的 value 。
// Switch Theme Dynamically
function switchTheme(event) {
if (event.target.checked) {
document.documentElement.setAttribute("data-theme", "dark");
localStorage.setItem("theme", "dark");
darkMode();
} else {
document.documentElement.setAttribute("data-theme", "light");
localStorage.setItem("theme", "light");
lightMode();
}
}
// Event Listener
toggleSwitch.addEventListener("change", switchTheme);
// Check Local Storage For Theme
const currentTheme = localStorage.getItem("theme");
if (currentTheme) {
document.documentElement.setAttribute("data-theme", currentTheme);
if (currentTheme === "dark") {
toggleSwitch.checked = true;
darkMode();
}
}
完整的Javascript程式碼
const toggleSwitch = document.querySelector('input[type="checkbox"]');
const toggleIcon = document.getElementById("toggle-icon");
const image = document.getElementById("picture");
// Dark Mode Styles
function darkMode() {
image.src = `img/undraw_aircraft_re_dark.svg`;
toggleIcon.children[0].textContent = "Dark Mode";
toggleIcon.children[1].classList.replace("fa-sun", "fa-moon");
}
// Light Mode Styles
function lightMode() {
image.src = `img/undraw_aircraft_re_light.svg`;
toggleIcon.children[0].textContent = "Light Mode";
toggleIcon.children[1].classList.replace("fa-moon", "fa-sun");
}
// Switch Theme Dynamically
function switchTheme(event) {
if (event.target.checked) {
document.documentElement.setAttribute("data-theme", "dark");
localStorage.setItem("theme", "dark");
darkMode();
} else {
document.documentElement.setAttribute("data-theme", "light");
localStorage.setItem("theme", "light");
lightMode();
}
}
// Event Listener
toggleSwitch.addEventListener("change", switchTheme);
// Check Local Storage For Theme
const currentTheme = localStorage.getItem("theme");
if (currentTheme) {
document.documentElement.setAttribute("data-theme", currentTheme);
if (currentTheme === "dark") {
toggleSwitch.checked = true;
darkMode();
}
}
文章參考
The Ultimate Guide on Designing a Dark Theme for your Android app.
Discussion