我如何检测暗模式使用JavaScript?

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中检测操作系统的首选配色方案?

105219 次浏览
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 媒体查询

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

要根据用户的首选项动态更新color-scheme,可以使用以下方法:

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


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


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

根据MediaQueryList - Web api | MDNaddListener是收听变化的正确方式。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元素上的::after不会让用户感到困惑,在after元素上添加display: none;

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元素的::after伪类。我们需要得到它的内容,只要确保你的CSS加载之前,你的JavaScript !'d'用于dark模式,'l'用于light模式。

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文档中学到了@media (prefers-color-scheme:用于检测的颜色方案)

我学会了如何获得计算风格的.content,因为我键入getComputedStyle(document.body,':after')时,它作为VSCode上的代码建议,并且它像我预期的那样工作。(如果我在一篇文章上看到它,我找不到我访问的哪篇文章)