Safari 中 @media (prefers-color-scheme: dark) 不生效,主因是旧版 Safari(12–15)对嵌套媒体查询、:root 变量前声明、动态注入 CSS 等场景会静默丢弃规则,且需确保 color-scheme: light dark 声明及 JS 同步打标与变量兜底。

@media (prefers-color-scheme: dark) 在 Safari 中不生效,不是你漏写了媒体查询,而是它压根没执行——要么被忽略,要么被覆盖,要么根本没收到信号。
为什么 Safari 会“假装没看见” prefers-color-scheme
旧版 Safari(12–15)对嵌套媒体查询、@media 写在 :root 变量声明之前、或用 <style> 标签动态插入 CSS 的情况,会直接跳过整块规则。它不报错,也不渲染,就像那行代码不存在。
-
@media (prefers-color-scheme: dark)必须写在所有:root变量定义之后,否则 Safari 14 及更早版本会静默丢弃 - 不要嵌套:
@media (max-width: 768px) { @media (prefers-color-scheme: dark) { ... } }→ Safari 15 以前全失效 - 内联
<style>或document.write注入的样式,可能绕过媒体查询重计算机制 - iOS WKWebView 默认不透传系统偏好,即使用户开了深色模式,
window.matchMedia('(prefers-color-scheme: dark)').matches仍返回false
为什么页面显示浅色,但 window.matchMedia 返回 true
说明 Safari 确实收到了信号,但你的 CSS 被更强的选择器或硬编码样式劫持了。常见于网站自己写了 body { background-color: #fff !important; },或者用了未适配的第三方组件。
规划您的迪拜之旅 — 哈利法塔观景、沙漠探险、迪拜购物中心购物、棕榈岛度假村及黄金市场砍价。还提供支持...
- 打开开发者工具(
Command + Option + I),选中<html>或<body>,右侧“样式”面板里搜color-scheme: light、background-color: #fff、!important - 逐个取消勾选这些声明,看页面是否立刻变暗——若变暗,就是它们在覆盖
- 检查是否有第三方 UI 库(如 Ant Design、MUI)注入了自己的主题类,和你的
@media规则冲突 - 别只改
body:按钮、输入框、表格、伪元素(::placeholder)、SVG 填充色都得单独适配,否则沿用浏览器默认浅色
如何让 Safari 真正“认账” dark mode
靠纯 CSS 媒体查询在 Safari 上太脆弱,必须加一层 JS 控制和 fallback。核心是:同步读取、同步打标、变量兜底。
立即学习“前端免费学习笔记(深入)”;
- 首屏 JS 同步执行:
document.documentElement.classList.toggle('dark', window.matchMedia('(prefers-color-scheme: dark)').matches) -
:root里先声明所有变量默认值:--bg: #fff; --text: #333;,再在@media和.dark里完整重写 - 所有用到颜色的地方加 fallback:
background: var(--bg, #fff); color: var(--text, #333); - 原生控件要显式声明:
:root { color-scheme: light dark; },否则<input>边框、滚动条在深色系统下仍是亮色 - 服务端渲染环境(Next.js、Nuxt)记得加
typeof window !== 'undefined'判断,否则 SSR 阶段报错
最麻烦的不是写多少 dark 规则,而是 Safari 对执行顺序和变量作用域极其严格——:root 里漏一个变量、@media 写错位置、没加 color-scheme 声明,都会导致整套逻辑静默失败。调试时别只盯着 CSS,先跑一遍 console.log(window.matchMedia(...).matches) 确认信号到底到了没有。

















