惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
人人都是产品经理
人人都是产品经理
爱范儿
爱范儿
WordPress大学
WordPress大学
T
Tor Project blog
Jina AI
Jina AI
美团技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
雷峰网
雷峰网
博客园 - 聂微东
B
Blog RSS Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 【当耐特】
Microsoft Azure Blog
Microsoft Azure Blog
S
SegmentFault 最新的问题
Recent Announcements
Recent Announcements
有赞技术团队
有赞技术团队
GbyAI
GbyAI
aimingoo的专栏
aimingoo的专栏
U
Unit 42
博客园 - Franky
Last Week in AI
Last Week in AI
阮一峰的网络日志
阮一峰的网络日志
Microsoft Security Blog
Microsoft Security Blog
F
Fortinet All Blogs
罗磊的独立博客
云风的 BLOG
云风的 BLOG
G
Google Developers Blog
大猫的无限游戏
大猫的无限游戏
Engineering at Meta
Engineering at Meta
C
Check Point Blog
Martin Fowler
Martin Fowler
The Cloudflare Blog
N
Netflix TechBlog - Medium
小众软件
小众软件
T
Tailwind CSS Blog
T
The Blog of Author Tim Ferriss
月光博客
月光博客
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
J
Java Code Geeks
Blog — PlanetScale
Blog — PlanetScale
P
Proofpoint News Feed
H
Help Net Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
The Exploit Database - CXSecurity.com
S
Securelist
I
Intezer
Spread Privacy
Spread Privacy

Wayne的博客

从 AI Coding 到 Agent Loop:2026H1 研发工具演进趋势 Awesome AI Prompts:提示词收集手册 | Wayne的博客 大模型缓存技术工程指南(下):面向缓存命中的 Prompt 与 Agent 工程实践 大模型缓存技术工程指南(上):从价格信号到推理缓存机制 | Wayne的博客 面向 AI / Agent 友好的 CLI 开发建议 【笔记】Harness Engineering(驾驭工程) | Wayne的博客 【笔记】location.href 和 location.assign 进行页面 URL 跳转 【工具】ZeroClaw配置项(config.toml)说明 | Wayne的博客 【工具】ZeroClaw配置项(config.toml)说明 | Wayne的博客 Skills 技术深度解析:AI Agent 能力扩展的新范式 | Wayne的博客 【笔记】浏览器PNA/LNA策略——记一次iframe中CORS报错的问题排查经历 | Wayne的博客 【工具】spec驱动开发解析 | Wayne的博客 Agent设计模式 | Wayne的博客 【工具】2025年AI Coding部分产品技术分析——ClaudeCode和CodexCLI | Wayne的博客 【工具】设计-开发-测试的AIGC产品清单梳理 | Wayne的博客 近期关于AI浪潮下的搜索引擎、SEO和GEO思考 | Wayne的博客 【工具】AI Common Notify:统一 AI 编程工具通知服务 21st.dev:让AI生成的页面告别"塑料感"的专业解决方案 | Wayne的博客 【笔记】Figma和AIGC(持续) | Wayne的博客 【笔记】State-Of-Ai 报告信息 | Wayne的博客 【笔记】19届阿里D2终端技术大会纪要 | Wayne的博客 【笔记】Lovable提示词指南 | Wayne的博客 【调研】AI 编程工具WindSurf使用技巧——WindsurfRules配置 | Wayne的博客 【AI】【笔记】MCP 协议:连接 AI 模型与外部世界的桥梁 | Wayne的博客 AI 前端编程工具的一个得力助手——CopyCoder | Wayne的博客
【笔记】web 黑夜模式通用适配方案 | Wayne的博客
2025-04-26 · via Wayne的博客

【笔记】web 黑夜模式通用适配方案

一、判断黑夜模式的方式

1.1 CSS 媒体查询判断黑夜模式的属性——prefers-color-scheme

prefers-color-scheme CSS 媒体特性用于检测用户是否有将系统的主题色设置为亮色或者暗色。 ——MDN

值:

  • no-preference:表示系统未得知用户在这方面的选项。在布尔值上下文中,其执行结果为 false。
  • light:表示用户已告知系统他们选择使用浅色主题的界面。
  • dark:表示用户已告知系统他们选择使用暗色主题的界面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

@media (prefers-color-scheme: light) {
html,
body {
color: black;
background-color: white;
}
}


@media (prefers-color-scheme: dark) {
html,
body {
color: white;
background-color: black;
}
}

1.1.1 兼容情况

除了 IE 外,其他主流浏览器基本都支持prefers-color-scheme

p-1.png

1.2 JavaScript 判断黑夜模式的属性——matchMedia

Window 的 matchMedia() 方法返回一个新的 MediaQueryList 对象,表示指定的媒体查询字符串解析后的结果。返回的 MediaQueryList 可被用于判定 Document 是否匹配媒体查询,或者监控一个 document 来判定它匹配了或者停止匹配了此媒体查询。 ——MDN

window.matchMedia(xxx) 返回一个 listenable-like 对象 MediaQueryList, 它继承自 EventTarget, 这意味着可以通过直接它获得最新的 MediaQuery 检测情况:

1
2
3
4
5
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {

} else {

}

1.2.1 监听主题变化

与 CSS 媒体查询不同,matchMedia 我们需要监听主题的变化作出对应处理,如下所示:

1
2
3
4
5
6
7
8
9
const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)');

darkModeQuery.addListener(e => {
if (e.matches) {

} else {

}
});

1.2.2 兼容情况

主流浏览器基本都支持matchMedia

p-2.png

二、黑夜模式样式适配处理方案

2.1 CSS 纯媒体查询实现

适用场景:需要快速实现、无需用户自定义主题的项目。如

1
2
3
4
5
6
7
@media (prefers-color-scheme: dark) {
body {
background-color: #1a1a1a;
color: #e0e0e0;
}

}

优缺点分析

优点:

  • 零 js 依赖,纯 css 实现
  • 系统级实时响应(跟随系统设置即时切换)
  • 维护成本最低

缺点:

  • 不能保存用户偏好(比如用户想覆盖系统设置)

2.2 CSS 变量 + 媒体查询

适用场景:中大型项目、需要多主题扩展、已使用 CSS 变量的代码库。

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
:root {
--bg-color: #ffffff;
--text-color: #333333;
}

@media (prefers-color-scheme: dark) {
:root {
--bg-color: #1a1a1a;
--text-color: #e0e0e0;
}
}

body {
background-color: var(--bg-color);
color: var(--text-color);
}

优缺点分析

优点:

  • 集中管理颜色变量
  • 方便扩展多主题
  • 支持渐进增强

缺点:

  • 仍无法保存用户偏好
  • 需要统一使用 CSS 变量规范

2.3 js matchMedia 动态切换 + 本地存储

适用场景:需要用户自定义主题的 ToC 产品、重视用户体验的 Web 应用。

如:

1
<button id="themeToggle">切换主题</button>
1
2
3
4
5
6
7
8
9
body.light-mode {
--bg-color: #ffffff;
--text-color: #333333;
}

body.dark-mode {
--bg-color: #1a1a1a;
--text-color: #e0e0e0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const themeToggle = document.querySelector('#themeToggle');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');


function initTheme() {
const savedTheme = localStorage.getItem('theme') || (prefersDark.matches ? 'dark' : 'light');
document.body.classList.add(`${savedTheme}-mode`);
}


themeToggle.addEventListener('click', () => {
document.body.classList.toggle('dark-mode');
document.body.classList.toggle('light-mode');
const currentTheme = document.body.classList.contains('dark-mode') ? 'dark' : 'light';
localStorage.setItem('theme', currentTheme);
});


prefersDark.addListener(e => {
if (!localStorage.getItem('theme')) {

document.body.classList.toggle('dark-mode', e.matches);
}
});

优缺点分析

优点:

  • 支持用户偏好保存
  • 同时响应系统和手动切换
  • 最佳用户体验

缺点:

  • 需要维护两套样式,依赖 js 处理。实现复杂度最高

2.4 js matchMedia 动态切换 + CSS-in-JS 运行时方案

适用场景:适合 React 等框架,已使用 CSS-in-JS 方案

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

import { createGlobalStyle, ThemeProvider } from 'styled-components';

const lightTheme = { bg: '#fff', text: '#333' };
const darkTheme = { bg: '#1a1a1a', text: '#e0e0e0' };

const GlobalStyle = createGlobalStyle`
body {
background: ${props => props.theme.bg};
color: ${props => props.theme.text};
}
`;

function App() {
const [isDark, setIsDark] = useState(window.matchMedia('(prefers-color-scheme: dark)').matches);

useEffect(() => {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handler = e => setIsDark(e.matches);
mediaQuery.addListener(handler);
return () => mediaQuery.removeListener(handler);
}, []);

return (
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
{}
</ThemeProvider>
);
}

优缺点分析

优点:

  • 完美配合组件化开发
  • 主题状态可全局管理
  • 支持动态主题切换

缺点:

  • 强依赖特定框架
  • 需要 CSS-in-JS 体系支持

2.5 *CSS 媒体查询 + filter 滤镜处理

适合场景:要求最快上线、或最小改动。本质其实也归属于方案 1(2.1)

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

@media (prefers-color-scheme: dark) {
html {
filter: invert(1) hue-rotate(180deg);
}


img,
video,
.logo,
.icon {
filter: invert(1) hue-rotate(180deg);
}
}

滤镜设置解释

整体滤镜处理可以概括为:反色 + 调整色相

  • invert(1): invert() 函数用于反转输入图像中的颜色。参数定义了转换的程度。如果参数是 1(或者 100%),则会完全反转颜色,即每个颜色通道的值都会被替换为其补色。例如:黑色变成白色,白色变为黑色等。
    • 当使用 invert(1) 时,则表示将图像的颜色彻底反转,即是:黑色变成白色,白色变为黑色。
  • hue-rotate(180deg): hue-rotate() 函数按照给定的角度旋转色彩轮上的颜色,其实就是冲淡颜色。这里的“角度”是指在标准色轮上转动多少度。色轮是一个圆形图表,显示了不同颜色如何根据它们的色调相互关联。
    • 当使用 hue-rotate(180deg) 时,意味着所有颜色都会在其原始位置基础上沿着色轮顺时针方向移动 180 度。比如红色会变成青色、绿色变成洋红色、蓝色变成黄色等,因为这些是在色轮上相对的颜色。

更多信息可见MDN - invertMDN - hue-rotate

兼容情况

除 IE 外,主流浏览器基本能支持。

p-3.png

优缺点分析

优点:

  • 开发和维护成本都是最低
  • 零 js 依赖,纯 css 实现
  • 系统级实时响应(跟随系统设置即时切换)

缺点:

  • 不能或很难自定义色值
  • 不能保存用户偏好(比如用户想覆盖系统设置)

三、黑夜模式色值设计标准

黑夜模式的色值设计和黑夜模式的工程实现没啥关系,属于用户体验保障。

3.1 WCAG 标准

WCAG(Web Content Accessibility Guidelines) 是由 W3C 制定的国际无障碍标准。其中颜色设置也是一项重要标准。

法律意义:WCAG 在美国《ADA 法案》、欧盟《EN 301 549》等法规中被引用

一些具体要求

  1. 核心要求
元素类型 最小对比度 例外场景
普通文本(<18pt/24px) 4.5:1 装饰性/禁用状态文本
大文本(≥18pt/24px) 3:1 粗体大文本(≥14pt/18.5px 粗体)
图形控件(图标/按钮) 3:1 纯装饰性图形
  1. 计算公式

使用相对亮度(Luminance)公式:

1
Contrast Ratio = (L1 + 0.05) / (L2 + 0.05)

其中:

  • L1 = 较亮颜色的相对亮度(0~1)
  • L2 = 较暗颜色的相对亮度(0~1)

实际开发中的应用

  1. 颜色选择示例
场景 通过示例 失败示例
白底黑字 #FFFFFF vs #000000 (21:1) #FFFFFF vs #666666 (5.74:1)
深色模式 #1A1A1A vs #E0E0E0 (10.3:1) #333333 vs #999999 (3.31:1)
  1. 调试工具

自动检测:

1
2
3
4
5
# Chrome DevTools
Styles面板 → 点击颜色选择器 → 显示对比度比率

# VS Code插件
"WCAG Color Contrast Checker"

在线工具:

  1. 设计技巧
1
2
3
4
5
6
7
8
9
10
11

:root {
--safe-dark-bg: #1a1a1a;
--safe-light-text: #e0e0e0;
--accent-color: #007bff;
}


button:disabled {
opacity: 0.6;
}

深度注意事项

  1. 动态场景:
  • 悬停/聚焦状态的对比度需保持合规
  • 渐变/阴影覆盖区域需取最差值验证
  1. 字体特性:
  • 300 以下字重需提高对比度要求
  • 衬线字体可能需要额外对比度补偿
  1. 环境适配:
  • 移动设备户外模式需考虑屏幕反光影响
  • OLED 屏幕需验证 PWM 调光下的可读性

法律合规案例

  • Target 诉讼案(2006):因对比度不足赔偿$6 百万
  • Domino’s 披萨案(2019):网站对比度违规败诉
  • 英国政府:强制要求所有公共网站通过 AA 认证

进阶建议

1.AAA 级目标:

  • 普通文本:7:1
  • 大文本:4.5:1
  1. 无障碍测试:
1
2
3
4
5

NVDA (Windows) / VoiceOver (Mac)


axe DevTools / Lighthouse

设计系统集成:

1
2
3
4
5
6
7
8
9
10
11

addon-a11y: {
config: {
contrast: {
thresholds: {
AA: 4.5,
AAA: 7
}
}
}
}

通过严格遵循这些标准,可确保您的深色模式既美观又合规。建议将对比度检测纳入 CI/CD 流程,实现自动化保障。


相关链接