乐趣区

关于javascript:前端如何实现黑夜模式

深色模式为目前网络倒退的一大趋势,能够看到大量的网站为了进步网站的体验都增加了深色模式。深色模式在光线有余的状况下看起来不会那么扎眼,可能很好的爱护咱们的眼睛。
在这边文章中次要讲如何应用 CSS 和 JS 实现深色模式和浅色模式的任意切换

剖析需要

假如有这么一个页面,咱们须要自在切换深色模式和浅色模式。那么就须要在不同模式应用不同的 css,这里能够通过两种形式一种是间接引入不同的 css 文件,另外一种通过更改 css 变量值的形式进行更改款式,上面是浅色模式的截图

具体实现

首先定义浅色模式的变量名和变量值

: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;
}

当切换场景的时候须要更改 css 变量的值,更改如下:

: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;
}

能够看到当切换到深色模式的时候,变量应用了更加暗的色彩,从而实现深色模式

更改 css

如何切换到暗模式有多种解决办法,在这里咱们应用媒体查问,prefers-color-scheme这个媒体查问可能获取到用户的零碎是否切换到了深色主题,具体如下:

@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;
  }
}

如果心愿用户能够通过抉择零碎的设置来切换浅色模式还是深色模式,那么下面这种形式就足够了。浏览的网站可能通过零碎设置抉择不同的款式
然而下面这种形式存在一个问题,就是用户心愿这个页面的模式不要追随系统配置的更改而更改。用户能够被动更改网站的模式,那么下面这种形式就不适合了

手动抉择模式

思路就是通过管制 js 来给元素增加不同的 class,不同的 class 领有不同的款式。首先增加在 html 中增加一个按钮用于切换不同的模式

<button id="toggle-button">toggle</button>
<script>
  const toggleButton = document.querySelector('#toggle-button')
</script>

而后须要中央存储用户的偏好设置,这里应用 localStorage 来存储用户的抉择。
而后给按钮增加事件用于切换主题,上面是具体的代码

  const toggleButton = document.querySelector('#toggle-button')
  
  toggleButton.addEventListener('click', (e) => {darkMode = localStorage.getItem('theme');
    if (darkMode === 'dark') {disableDarkMode();
    } else {enableDarkMode();
    }
  });

  function enableDarkMode() {localStorage.setItem('theme', 'dark');
  }

  function disableDarkMode() {localStorage.setItem('theme', 'light');
  }

当初咱们就能够存储这个用户的偏好设置。而后不同的主题下给 body 元素增加不同的class,具体如下

 function enableDarkMode() {document.body.classList.add("dark-mode")
    localStorage.setItem('theme', 'dark');
  }

  function disableDarkMode() {document.body.classList.remove("dark-mode")
    localStorage.setItem('theme', 'light');
  }

和媒体查问一样,在 dark-mode 的状况下更改 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;
}

同时在进入这个页面的时候须要获取到用户的偏好设置,从 localStorage 中读取

let darkMode = localStorage.getItem("theme")

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

这次就能够在页面刷新当前依然拿到用户的偏好设置。
然而这种计划依然存在肯定的问题,就是咱们冀望用户没有抉择模式的时候,页面的模式可能追随用户自身零碎的设置而更改

最终计划

window 上有个办法叫matchMedia,咱们能够通过它获取以后用户零碎处于什么模式,具体代码如下:

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

这样就能保障用户在没有设置偏好的时候应用默认的零碎主题,残缺代码如下:

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")
  }

  function disableDarkMode() {document.body.classList.remove("dark-mode")
    localStorage.setItem("theme", "light")
  }
  window
  .matchMedia("(prefers-color-scheme: dark)")
  .addListener(e => (e.matches ? enableDarkMode() : disableDarkMode()))

欢送关注「前端好好学」,前端学习不迷路或加微信 ssdwbobo,一起交流学习

退出移动版