Windows和macOS现在有黑暗模式。

对于CSS,我可以使用:

@media (prefers-dark-interface) { 
  color: white; background: black 
}

但是我使用的是Stripe Elements API,它把颜色放在JavaScript中

例如:

const stripeElementStyles = {
  base: {
    color: COLORS.darkGrey,
    fontFamily: `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"`,
    fontSize: '18px',
    fontSmoothing: 'antialiased',
    '::placeholder': {
      color: COLORS.midgrey
    },
    ':-webkit-autofill': {
      color: COLORS.icyWhite
    }
  }
}

如何在JavaScript中检测操作系统的首选配色方案?


if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
    // dark mode
}

注意变化:

window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
    const newColorScheme = event.matches ? "dark" : "light";
});

你可以直接用JavaScript检查CSS Media-Queries

window.matchMedia()方法返回一个MediaQueryList对象 表示指定CSS媒体查询字符串的结果。的 的任何媒体特性 CSS @media规则,如min-height, min-width, orientation等。

要检查Media-Query是否为真,可以使用matches属性

// Check to see if Media-Queries are supported
if (window.matchMedia) {
  // Check if the dark-mode Media-Query matches
  if(window.matchMedia('(prefers-color-scheme: dark)').matches){
    // Dark
  } else {
    // Light
  }
} else {
  // Default (when Media-Queries are not supported)
}

要根据用户的偏好动态更新配色方案,可以使用以下方法:

function setColorScheme(scheme) {
  switch(scheme){
    case 'dark':
      console.log('dark');
      
      break;
    case 'light':
      console.log('light');
      // Light
      break;
    default:
      // Default
      console.log('default');
      break;
  }
}

function getPreferredColorScheme() {
  if (window.matchMedia) {
    if(window.matchMedia('(prefers-color-scheme: dark)').matches){
      return 'dark';
    } else {
      return 'light';
    }
  }
  return 'light';
}

function updateColorScheme(){
    setColorScheme(getPreferredColorScheme());
}

if(window.matchMedia){
  var colorSchemeQuery = window.matchMedia('(prefers-color-scheme: dark)');
  colorSchemeQuery.addEventListener('change', updateColorScheme);
}

updateColorScheme();

根据MediaQueryList - Web api | MDN, addListener是监听更改的正确方式。addEventListener在iOS 13.4上不为我工作。

window.matchMedia('(prefers-color-scheme: dark)').addListener(function (e) {
  console.log(`changed to ${e.matches ? "dark" : "light"} mode`)
});

如果你使用nuxt开发应用,你需要彩色模式。


检查matchMedia选项:

function getTheme() {
  if(window.matchMedia && window.matchMedia("(prefers-color-scheme:dark)").matches) {
    return "dark";
  } else {
    return "light";
  }
}

在输入JavaScript之前:

您可以使用CSS创建一个@media查询,表示在body元素上有一个::after伪类,根据用户的配色方案,body元素具有不同的文本。为了确保body元素后面的::不会让用户感到困惑,添加一个display: none;对after元素。

CSS代码:

@media (prefers-color-scheme:dark){
    body::after{
        content: 'd';
        display: none;
    }
}
@media (prefers-color-scheme:light){
    body::after{
        content: 'l';
        display: none;
    }
}

现在你的JavaScript:

因为我们在文档中有一个对象要选择,所以我们可以在body元素的伪类之后获得::。我们需要得到它的内容,只要确保你的CSS加载之前,你的JavaScript !'d'表示暗模式,'l'表示亮模式。

JavaScript代码:

var colorScheme = getComputedStyle(document.body,':after').content;
// d for dark mode, l for light mode.

为什么这是有用的

你可以在CSS和HTML中这样做,但为什么要在JavaScript中这样做呢?

您将使用JavaScript,因为您可能必须添加img元素,但图像有文本,因此您有两张图像,一张用于浅色模式,另一张用于深色模式。因此,您可以使用JavaScript根据颜色方案将img元素的src属性值更改为正确的URL。

可能还有更多的用途,但这是我能想到的用途。

来源:

我从这篇stackoverflow文章中学到了getComputedStyle函数。

我从MDN Web Docs学习了@media (prefer - colour -scheme:要检测的配色方案)。

我学会了如何从看到它作为一个代码建议在VSCode,因为我键入getComputedStyle(document.body,':after')和它的工作,我期望它。content的计算样式。(如果我在一篇文章上看到它,我找不到我访问的哪篇文章)


对于使用react的人,请参阅useDarkMode钩子。它可以监听变化,还可以切换/改变暗模式。

import { useDarkMode } from 'usehooks-ts'

export default function Component() {
  const { isDarkMode, toggle, enable, disable } = useDarkMode()
  return (
    <div>
      <p>Current theme: {isDarkMode ? 'dark' : 'light'}</p>
      <button onClick={toggle}>Toggle</button>
      <button onClick={enable}>Enable</button>
      <button onClick={disable}>Disable</button>
    </div>
  )
}