JavaScript 中最佳的亮/暗模式主题切换
学习如何使用 JavaScript、CSS 自定义属性、本地存储和系统设置,为您的网站构建终极主题切换™️。无需任何框架!
我以前很不赞同明暗模式的切换。“切换按钮就是用户系统偏好设置!”我会天真地喊道,然后选择让prefers-color-scheme CSS 媒体查询控制我个人网站的主题。没有切换按钮,别无选择。🫠
自从黑暗模式流行起来以来,我就一直是它的用户。但最近,我更喜欢在浅色模式下使用一些网站和工具——包括我的个人网站——同时将我的系统设置牢牢地保持在黑暗模式。我需要一个切换开关。我需要一个选择!其他人也一样。
在这篇文章中,我将向您展示如何使用 JavaScript 为我的网站构建 The Ultimate Theme Toggle™️:
- 在本地浏览器存储中存储和检索主题偏好设置,
- 恢复用户系统偏好设置,
- 如果未检测到以上任何内容,则恢复为默认主题。
TL;DR:这是 CodePen 上的代码。
向 HTML 标签添加数据属性
在你的 HTML 标签上,添加一个数据属性,例如 ,data-theme
并赋予其默认值“亮”或“暗”。过去我使用过自定义属性color-mode
而不是数据属性(例如color-mode="light"
)。虽然这种方法有效,但它不属于有效的 HTML,而且我找不到任何相关文档!非常感谢任何关于这方面的见解。😅
<html lang="en" data-theme="light">
<!-- all other HTML -->
</html>
通过 CSS 自定义属性配置主题
在 CSS 中,通过CSS 自定义属性(或变量)在每个属性值下配置主题颜色data-theme
。请注意,您不一定需要:root
与 结合使用data-theme
,但对于不随主题变化的全局属性(如下例所示)很有用。在 MDN 上了解有关 :root CSS 伪类的更多信息。
:root {
--grid-unit: 1rem;
--border-radius-base: 0.5rem;
}
[data-theme="light"] {
--color-bg: #ffffff;
--color-fg: #000000;
}
[data-theme="dark"] {
--color-bg: #000000;
--color-fg: #ffffff;
}
/* example use of CSS custom properties */
body {
background-color: var(--color-bg);
color: var(--color-fg);
}
在 HTML 标签上手动切换data-theme
属性,您将看到主题已经发生变化(只要您使用这些 CSS 属性来设置元素样式)!
在 HTML 中构建切换按钮
在您的网站标题或任何需要切换主题的位置添加一个 HTML 按钮。添加一个data-theme-toggle
属性(稍后我们将使用它在 JavaScript 中定位按钮),如果您打算在按钮上使用图标(例如,分别用太阳和月亮来表示明暗模式),请添加一个aria-label,以便屏幕阅读器和辅助技术能够理解交互式按钮的用途。
<button
type="button"
data-theme-toggle
aria-label="Change to light theme"
>Change to light theme (or icon here)</button>
页面加载时计算主题设置
在这里,我们将根据我所说的“偏好级联”来计算主题设置。
从本地存储获取主题偏好
我们可以使用JavaScript 中的 localStorage 属性将用户偏好设置保存在浏览器中,这些偏好设置会在会话之间持续存在(或直到手动清除)。在 The Ultimate Theme Toggle™️ 中,存储的用户偏好设置是最重要的设置,因此我们首先会查找它。
页面加载时,使用localStorage.getItem("theme")
来检查之前存储的偏好设置。稍后我们将在每次按下切换按钮时更新主题值。如果没有本地存储值,则该值为null
。
// get theme on page load
localStorage.getItem("theme");
// set theme on button press
localStorage.setItem("theme", newTheme);
使用 JavaScript 检测用户系统设置
如果 中没有存储主题偏好设置,我们将使用window.matchMedia() 方法localStorage
通过传入媒体查询字符串来检测用户的系统设置。您只需为偏好设置级联计算一项设置,但以下代码展示了如何检测亮色或暗色系统设置。
const systemSettingDark = window.matchMedia("(prefers-color-scheme: dark)");
// or
const systemSettingLight = window.matchMedia("(prefers-color-scheme: light)");
window.matchMedia()
返回一个MediaQueryList
包含您请求的媒体查询字符串,以及它是否matches
(true/false)用户系统设置。
{
matches: true,
media: "(prefers-color-scheme: dark)",
onchange: null
}
恢复默认主题
现在您可以通过访问localStorage
值和系统设置window.matchMedia()
,您可以使用首选项级联(本地存储,然后是系统设置)计算首选主题设置,并恢复到您选择的默认主题(应该是您之前在 HTML 标签上指定的默认主题)。
我们将在页面加载时运行此代码来计算当前主题设置。
function calculateSettingAsThemeString({ localStorageTheme, systemSettingDark }) {
if (localStorageTheme !== null) {
return localStorageTheme;
}
if (systemSettingDark.matches) {
return "dark";
}
return "light";
}
const localStorageTheme = localStorage.getItem("theme");
const systemSettingDark = window.matchMedia("(prefers-color-scheme: dark)");
let currentThemeSetting = calculateSettingAsThemeString({ localStorageTheme, systemSettingDark });
向切换按钮添加事件监听器
接下来,我们将设置一个事件监听器,以便在按钮按下时切换主题。使用data-theme-toggle
我们之前添加的 data 属性 ( ) 在 DOM 中定位按钮,并在点击时为按钮添加一个事件监听器。下面的示例相当冗长,你可能需要将下面的一些功能抽象成实用函数(我在CodePen 上的示例中已经这样做了)。让我们来演示一下:
- 将新主题计算为字符串
- 计算并更新按钮文本(如果您在按钮上使用图标,则可以在此处进行切换)
- 更新按钮上的 aria-label
- 切换 HTML 标签上的 data-theme 属性
- 将新的主题偏好设置保存在本地存储中
- 更新内存中的 currentThemeSetting
// target the button using the data attribute we added earlier
const button = document.querySelector("[data-theme-toggle]");
button.addEventListener("click", () => {
const newTheme = currentThemeSetting === "dark" ? "light" : "dark";
// update the button text
const newCta = newTheme === "dark" ? "Change to light theme" : "Change to dark theme";
button.innerText = newCta;
// use an aria-label if you are omitting text on the button
// and using sun/moon icons, for example
button.setAttribute("aria-label", newCta);
// update theme attribute on HTML to switch theme in CSS
document.querySelector("html").setAttribute("data-theme", newTheme);
// update in local storage
localStorage.setItem("theme", newTheme);
// update the currentThemeSetting in memory
currentThemeSetting = newTheme;
});
要确认localStorage
正在更新,请打开您的开发工具,导航至Application
相应标签页,展开Local Storage
并选择您的网站。您将看到一个键值列表;找到theme
并点击按钮即可实时查看更新。刷新页面,您将看到主题偏好设置已保存!
把它们放在一起!
您现在可以通过以下方式构建您自己的 Ultimate Theme Toggle™️:
- 使用 CSS 自定义属性指定不同的主题颜色,通过 HTML 标签上的数据属性切换
- 使用 HTML 按钮来切换
- 使用偏好级联(本地存储 > 系统设置 > 后备默认主题)计算页面加载时的首选主题
- 单击切换按钮即可切换主题,并将用户偏好存储在浏览器中以供将来访问
这是完整的 CodePen,你可以在我的个人网站上查看实际运行版本。祝你使用愉快!
文章来源:https://dev.to/whitep4nth3r/the-best-lightdark-mode-theme-toggle-in-javascript-368f