Playwright无直接深色模式API,需用addInitScript注入JS模拟prefers-color-scheme;--force-dark-mode仅影响Chromium外壳;page.emulateMedia(colorScheme)不支持。

Playwright 本身不直接提供“开启/关闭深色模式”的 API,它没有 page.setDarkMode(True) 这样的方法。深色模式的控制依赖于操作系统级偏好或页面内 CSS 媒体查询(@media (prefers-color-scheme: dark)),而 Playwright 只能通过模拟系统偏好或注入 CSS 来间接影响它。
用 context.addInitScript() 注入 @media 规则强制触发深色样式
这是最常用、最可靠的方式:绕过系统检测,直接让页面认为用户启用了深色模式。适用于测试深色主题 UI 或截图对比。
- 必须在
browser.new_context()后、context.new_page()前调用context.addInitScript(),否则脚本不会注入到后续所有页面 - 注入内容是 JS 字符串,需动态覆盖
window.matchMedia的返回值,例如:context.addInitScript("""() => { const originalMatchMedia = window.matchMedia; window.matchMedia = (query) => { if (query === '(prefers-color-scheme: dark)') { return { matches: true, addListener: () => {}, removeListener: () => {} }; } return originalMatchMedia(query); }; }""") - 若要切回浅色模式,把
matches: true改成matches: false即可;不同页面需新建 context,不能热切换 - 注意:部分网站会读取
document.documentElement.classList或 localStorage 主动设置主题,此时还需额外模拟(比如page.evaluate(() => document.documentElement.classList.add('dark')))
启动浏览器时传入 --force-dark-mode(仅 Chromium)
Chromium 支持原生 flag 强制启用深色 UI(地址栏、右键菜单等),但对网页内 prefers-color-scheme 无效——它只影响浏览器外壳,不触发 CSS 媒体查询。
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
- 仅限
chromium浏览器,Firefox 和 WebKit 不支持该 flag - 必须在
playwright.chromium.launch()时通过args传入:browser = playwright.chromium.launch(args=['--force-dark-mode'])
- 这个 flag 不会影响网页渲染逻辑,所以如果你的目标是验证页面深色样式是否生效,它没用;只有当你需要截图包含深色浏览器 UI 时才考虑
- Windows/macOS 系统级深色模式已开启时,此 flag 可能被忽略或行为不一致,建议显式关闭系统深色模式再测试
为什么 page.emulateMedia() 对深色模式无效?
很多人尝试用 page.emulateMedia(colorScheme='dark'),但它在 Playwright 当前版本(v1.40+)中**不被支持**,调用会静默失败或抛出 TypeError: emulateMedia: Unknown option colorScheme 错误。
立即学习“Python免费学习笔记(深入)”;
-
page.emulateMedia()目前只支持media('screen'/'print')、colorScheme在 Playwright 中尚未实现(截至 2024 年中),文档也未列出该参数 - 不要依赖社区旧教程里出现的
colorScheme='dark'示例,它们多基于早期 patch 或 fork 版本,主线不兼容 - 替代方案就是上面提到的
addInitScript—— 它稳定、跨浏览器、可控性强
真正麻烦的地方在于:深色模式不是单一开关,而是由系统偏好、浏览器 flag、JS 检测、CSS 类、localStorage 多层叠加决定的。Playwright 能精确控制的只有 JS 层和部分 Chromium flag,其他环节得靠你主动补全模拟逻辑。别指望一个函数调用就搞定全部。

















