在网页上轻松使用暗黑模式

2025-05-25

在网页上轻松使用暗黑模式

这篇文章最初发表在我的博客上

黑暗模式🌒是过去几年的一种趋势,你会发现几乎所有网站都启用了该模式,包括像 Twitter 这样的知名网站,黑暗模式如此受欢迎的主要原因是,在光线不足的地方,人眼在昏暗的背景上看到浅色文字比反之要好得多。

在这篇简短的文章中,我试图向您展示如何使用 CSS 和 JavaScript 轻松实现该功能。

假设

我们有一个小型 HTML 页面,默认情况下具有浅色主题,我们需要实现深色主题以及为访问者提供选项,因此基本上我们可以通过更改 CSS 的变量来轻松做到这一点,无论是 CSS 的自定义属性--primary-color还是使用 Sass$primary-color或任何其他方式。

这是浅色主题的样子

浅色主题示例

解释

让我们首先看一下我们拥有的 CSS 变量(不用担心,整个代码都在文章末尾提到的 GitHub repo 上)

:root {
  --primary-bg: #eee;
  --primary-fg: #000;
  --secondary-bg: #ddd;
  --secondary-fg: #555;
  --primary-btn-bg: #000;
  --primary-btn-fg: #fff;
  --secondary-btn-bg: #ff0000;
  --secondary-btn-fg: #ffff00;
  --image-opacity: 1;
}

// here is the rest of the CSS styles
Enter fullscreen mode Exit fullscreen mode

主要目标是将这些变量值更改为以下内容:

:root {
  --primary-bg: #282c35;
  --primary-fg: #fff;
  --secondary-bg: #1e2129;
  --secondary-fg: #aaa;
  --primary-btn-bg: #ddd;
  --primary-btn-fg: #222;
  --secondary-btn-bg: #780404;
  --secondary-btn-fg: #baba6a;
  --image-opacity: 0.85;
}
Enter fullscreen mode Exit fullscreen mode

仅当我们有dark mode用户的偏好时,上述变量才是相同的变量名称,只有不同的值才能使主题变暗,因为每当您定义相同的变量两次时,后一个变量就会覆盖第一个变量。

仅使用 CSS 实现

我们有几种方法可以解决这个问题,例如prefers-color-scheme在 CSS 中使用媒体查询,如果媒体查询匹配,则将启用颜色变量列表,如下所示:

@media (prefers-color-scheme: dark) {
  :root {
    --primary-bg: #282c35;
    --primary-fg: #fff;
    --secondary-bg: #1e2129;
    --secondary-fg: #aaa;
    --primary-btn-bg: #ddd;
    --primary-btn-fg: #222;
    --secondary-btn-bg: #780404;
    --secondary-btn-fg: #baba6a;
    --image-opacity: 0.85;
  }
}
Enter fullscreen mode Exit fullscreen mode

它在大多数现代浏览器中都得到了很好的支持,当然 IE11 除外。

在这种情况下,您不必为用户实现切换按钮,因为您的网站无论如何都会遵循用户偏好。

User preference:在现代操作系统中,您可以在设置中将操作系统的常规主题更改为深色或浅色,并通过在 CSS 中添加上述代码,它将从操作系统获取用户偏好,并根据用户的偏好显示网站,这是一个很棒的技巧💫

这是黑暗模式下的样子:

暗模式示例

但是,如果用户喜欢以轻量模式预览您的网站而不管操作系统的偏好如何,您可能会遇到一个问题,在这种情况下,您必须实现一个按钮供用户切换到他们自己的偏好。

实现切换按钮 (JavaScript)

让我们首先在 HTML 文件末尾的正文关闭之前添加一个简单的脚本标签,然后在其中选择我们要用作暗模式切换的按钮。

// here is the button
<div id="dark-mode-toggle" title="Dark mode toggle">🌒</div>
... // here is the script tag
<script>
  const toggleButton = document.querySelector("#dark-mode-toggle")
</script>
Enter fullscreen mode Exit fullscreen mode

现在我们应该考虑一种方法来保存和保留用户偏好,而最好的解决方案就是localStorage

让我们监听该按钮的点击并检查themelocalStorage 中的键值是否将dark其转换为light并更改该图标,否则执行相反的操作。

脚本如下:

<script>
  const toggleButton = document.querySelector('#dark-mode-toggle');

  toggleButton.addEventListener('click', (e) => {
    darkMode = localStorage.getItem('theme');
    if (darkMode === 'dark') {
      disableDarkMode();
    } else {
      enableDarkMode();
    }
  });

  function enableDarkMode() {
    localStorage.setItem('theme', 'dark');
    toggleButton.innerHTML = '☀️';
  }

  function disableDarkMode() {
    localStorage.setItem('theme', 'light');
    toggleButton.innerHTML = '🌒';
  }
</script>
Enter fullscreen mode Exit fullscreen mode

现在我们有一个按钮功能,可以将themelocalStorage 中的键从更改lightdark,反之亦然,并且它还可以切换图标来显示某些内容,但是,我们仍然没有达到我们的目标。

这里的想法是创建一个包装类,它将保存暗模式 CSS 变量,并根据条件添加/删除该类,以及在正文中使用的最佳元素。

首先修改 CSS 并创建该类,如下所示:

.dark-mode {
  --primary-bg: #282c35;
  --primary-fg: #fff;
  --secondary-bg: #1e2129;
  --secondary-fg: #aaa;
  --primary-btn-bg: #ddd;
  --primary-btn-fg: #222;
  --secondary-btn-bg: #780404;
  --secondary-btn-fg: #baba6a;
  --image-opacity: 0.85;
}
Enter fullscreen mode Exit fullscreen mode

然后让我们转到脚本来稍微改变一下功能:

function enableDarkMode() {
  document.body.classList.add("dark-mode")
  localStorage.setItem("theme", "dark")
  toggleButton.innerHTML = "☀️"
}

function disableDarkMode() {
  document.body.classList.remove("dark-mode")
  localStorage.setItem("theme", "light")
  toggleButton.innerHTML = "🌒"
}
Enter fullscreen mode Exit fullscreen mode

现在,单击切换按钮后,功能应该可以正常工作,如下所示:

暗光模式切换功能

还有一点需要注意的是,如果这是 localStorage 中的设置,则在重新加载时您将无法获得暗模式,解决方案很简单,只需在脚本开头添加它即可。

let darkMode = localStorage.getItem("theme")

if (darkMode === "dark") enableDarkMode()
Enter fullscreen mode Exit fullscreen mode

就是这样,你现在可以走了,但在这种情况下,我们丢失了在使用媒体查询之前实现的用户偏好,好消息是我们可以在 Javascript 中监听它并执行以下操作:

window
  .matchMedia("(prefers-color-scheme: dark)")
  .addListener(e => (e.matches ? enableDarkMode() : disableDarkMode()))
Enter fullscreen mode Exit fullscreen mode

通过使用上述代码,每当用户改变他的偏好时,您的网站就会遵循这一点,最后我们有一个完整的解决方案,这是完整的脚本标签:

<script>
  const toggleButton = document.querySelector("#dark-mode-toggle")
  let darkMode = localStorage.getItem("theme")

  if (darkMode === "dark") enableDarkMode()

  toggleButton.addEventListener("click", e => {
    darkMode = localStorage.getItem("theme")
    if (darkMode === "dark") {
      disableDarkMode()
    } else {
      enableDarkMode()
    }
  })

  function enableDarkMode() {
    document.body.classList.add("dark-mode")
    localStorage.setItem("theme", "dark")
    toggleButton.innerHTML = "☀️"
  }

  function disableDarkMode() {
    document.body.classList.remove("dark-mode")
    localStorage.setItem("theme", "light")
    toggleButton.innerHTML = "🌒"
  }

  window
    .matchMedia("(prefers-color-scheme: dark)")
    .addListener(e => (e.matches ? enableDarkMode() : disableDarkMode()))
</script>
Enter fullscreen mode Exit fullscreen mode

结论

😅 呼,就是这样,一个简单但重要的解决方案,现在非常流行,您可以在Github repo上找到整个代码示例,我希望您在本快速教程中学到了一些新东西。

如果您需要任何帮助,请随时在 Twitter 上与我分享或讨论,或者关注我并让我们成为朋友。

如果您懂阿拉伯语,这里有阿拉伯语教程中的逐步解释:
https://youtu.be/QC0PMPhq6CM

孩子们👋

文章来源:https://dev.to/medhatdawoud/dark-mode-easily-on-the-web-5h6a
PREV
CSS 中带有曲线和 3D 运动的渐变边框(Nextjs 票证克隆)
NEXT
16 个简单技巧,提升您的工作效率 x10 1. 删除通知🔔 2. 分割您的时间🍕 3. Inbox0📥 4. 找到您的流程🕯️ 5. 使用 Zenware💭 6. 关闭浏览器标签🔓 7. 为所有东西找到归宿🏠 8. 制定每日议程📅 9. 自动执行重复性任务🤖 10. 避免无效会议🤝 11. 避免多任务处理👨‍💼 12. 避免语音通话📞 13. 清晨吃掉青蛙🌤️ 14. 不要重复使用每日待办事项清单✔️ 15. 衡量目标📈 16. 不要保存以备后用🍓 [更新] 第二部分