如何检测用户的操作系统是否更喜欢暗模式并使用 CSS 和 JS 更改您的站点

184 阅读6分钟

如何检测用户的操作系统是否更喜欢暗模式并使用 CSS 和 JS 更改您的站点

原文链接:www.hanselman.com/blog/how-to…

img我收到了Stevö John发来的一条推文,他说他发现我博客的现有浅色主题在他生活在黑暗模式下时很刺耳。我以前从未真正考虑过,但一旦他说出来,就很明显了。我不仅应该支持暗模式,还应该检测用户的偏好并无缝切换。如果浏览器或操作系统也发生变化,我也应该支持更改模式。Stevö 很友好地发送了一些示例 CSS 和一些链接,所以我开始探索这个主题。

在使用首选颜色方案和检测暗模式时,需要考虑以下几点:

  • 尽可能使用现有的主题。
    • 如果可以避免的话,我不想拥有 style.css 和 style-dark.css。否则这将是一个维护噩梦。
  • 使其适用于我的所有网站
  • 考虑第 3 方小部件
    • 我为我的博客使用了语法高亮器(非常非常老),我的播客使用 Simplecast 的播客 HTML5 播放器。我不喜欢黑暗模式,然后有一个很大的旧 LIGHT MODE 播客播放器吓跑人们。因此,我需要上下文贯穿始终。
  • 考虑页面的初始状态以及舞台的变化。
    • 当然,我可以在您加载页面时让页面看起来不错,如果您在查看页面的过程中更改模式(从暗到亮和向后),它也应该改变,对吗?还要考虑上述所有要求。

您可以将 Chrome/Edge 浏览器设置为使用系统设置、浅色或深色。在设置中搜索主题。

img

所有这些,我只能在午餐时间做,因为这个博客不是我真正的日常工作。我们走吧!

首选颜色方案 CSS 媒体查询

我喜欢 CSS @media 查询,并且多年来一直使用它们来支持移动和平板电脑设备。今天,它们是响应式设计的主要内容。原来你可以只使用@media 查询来查看用户是否更喜欢暗模式

@media (prefers-color-scheme: dark) {

甜的。这里的任何内容(CSS 中的 C 代表级联,记住)将覆盖之前的内容。这是我更改的一些入门规则。我只是在 F12 工具检查器中更改内容,然后将它们收集回我的主 CSS 页面。如果您是具有设计系统的有组织的 CSS 人员,您也可以使用变量。

这些只是一些,但你明白了。请注意 .line-tan 示例,我还说“只需将其恢复为初始值。”这通常比提出“相反”值容易得多,在这种情况下,这意味着生成一些 PNG。

@media (prefers-color-scheme: dark) {
    body {
        color: #b0b0b0;
        background-color: #101010;
    }
 
    .containerOuter {
        background-color: #000;
        color: #b0b0b0;
    }
 
    .blogBodyContainer {
        background-color: #101010;
    }
 
    .line-tan {
        background: initial;
    }
 
    #mainContent {
        background-color: #000;
    }
...snip...
}

甜的。这个对我的主要 css 的更改适用于hanselman.com主站点。让我们现在做博客,其中包括第 3 方语法荧光笔。我使用与我的主站点相同的基本规则,但也不得不(对不起 CSS 伙计们)用这个非常古老的语法荧光笔变得激进和过于重要,就像这样:

@media (prefers-color-scheme: dark) {
    .syntaxhighlighter {
        background-color: #000 !important
    }
 
    .syntaxhighlighter .line.alt1 {
        background-color: #000 !important
    }
 
    .syntaxhighlighter .line.alt2 {
        background-color: #000 !important
    }
 
    .syntaxhighlighter .line {
        background-color: #000 !important
    }
...snip...
}

您的里程可能会有所不同,但这一切都取决于工具。如果没有 !important ,我就无法完成这项工作,有人告诉我这是不受欢迎的。我很抱歉。

使用 JavaScript 检测暗模式首选项

我用于播客的第三方控件类似于很多控件,它是一个 iFrame。因此,它需要一些参数作为 URL 查询字符串参数。

我像这样生成 iFrame:

<iframe id='simpleCastPlayeriFrame'
title='Hanselminutes Podcast Player'
frameborder='0' height='200px' scrolling='no'
seamless src='https://player.simplecast.com/{sharingId}'
width='100%'></iframe>

如果我在查询字符串中添加“dark=true”,我将获得不同的玩家皮肤。这只是一个示例,但通常 3rd 方集成需要 queryString 或变量或自定义 CSS。您需要与您的供应商合作,以确保他们不仅关心暗模式(感谢Simplecast!),而且他们有办法像这样轻松启用它。

img

但这引入了一些有趣的问题。我需要使用 JavaScript 检测偏好并确保加载了正确的播放器。

我还想注意主题是否更改(从亮到暗或返回)并动态更改我的 CSS(该部分由浏览器自动发生)和此播放器(必须手动完成,因为暗模式是通过 URL 调用的)查询字符串段。)

这是我的代码。同样,不是 JavaScript 专家,但这对我来说很自然。如果它不是超级惯用语或者它只是很糟糕,请给我发电子邮件,我会进行更新。我确实检查 window.matchMedia 至少不会在出现旧浏览器时感到害怕。

if (window.matchMedia) {
  var match = window.matchMedia('(prefers-color-scheme: dark)')
  toggleDarkMode(match.matches);
 
  match.addEventListener('change', e => {
      toggleDarkMode(match.matches);
  })
 
  function toggleDarkMode(state) {
      let simpleCastPlayer = new URL(document.querySelector("#simpleCastPlayeriFrame").src);
      simpleCastPlayer.searchParams.set("dark", state);
      document.querySelector("#simpleCastPlayeriFrame").src = simpleCastPlayer.href;
  }
}

toggleDarkMode 是一种方法,因此我可以将它用于初始状态和“更改”状态。它使用 URL 对象,因为解析字符串太晚了。我设置了 searchParams 而不是 .append 因为我知道它总是被设置。我设置了

在我写这篇文章时,我以为我可以像存储 matchMedia 一样存储 document.querySelector(),但我现在才看到它。该死的。尽管如此,它仍然有效!所以我#shipit。

我确定我错过了一两页或一三个元素,所以如果您发现白页或错误,请在此处提交github.com/shanselman/…,我会采取一有空就看看。

总而言之,一个有趣的午餐时间。感谢Stevö的推动!

现在,亲爱的读者,您可以为浅色模式和深色模式更新您的网站。

发起人: 开发者选择 Couchbase 的第一大理由?您可以使用现有的 SQL++ 技能轻松查询和访问 JSON。以更少的培训获得更多的力量和灵活性。了解更多。

关于斯科特

Scott Hanselman 是前教授,前金融首席架构师,现在是演讲者、顾问、父亲、糖尿病患者和微软员工。他是一个失败的单口相声喜剧演员,也是一位作家和作家。