无法用纯CSS实现电池电量样式切换,因浏览器未实现battery-level等媒体特性;必须用JS调用navigator.getBattery()获取状态并动态添加类名控制样式,同时需处理Safari不支持、事件失效等兼容性问题。

目前无法用纯 CSS 实现基于真实电池状态的样式切换。 浏览器不暴露 navigator.getBattery() 的结果给 CSS 媒体查询,所谓 “Scripting media feature” 仍处于 W3C 提案阶段(environment 或 system-color-scheme 类扩展),未被任何主流浏览器实现。
为什么不能直接写 @media (battery-level: <= 20%)
这不是语法错误,而是根本不存在的媒体特性。当前所有浏览器(Chrome、Safari、Firefox、Edge)的 @media 支持列表里没有与电池电量、温度、CPU 负载等运行时系统状态挂钩的特性。W3C 的 Media Queries Level 5 Draft 中曾讨论过 scripting、environment 等占位符,但至今无引擎落地。硬写这类规则,浏览器会静默忽略整条 @media 块。
真实可行的替代路径:JS 检测 + class 切换
必须用 JavaScript 获取电池状态,并主动触发样式变更。关键点不是“能不能”,而是“怎么稳”:
- 调用
navigator.getBattery()返回 Promise,需处理拒绝情况(如 Safari 完全禁用该 API,部分 Android WebView 也屏蔽) - 监听
battery.levelchange事件比轮询更省资源,但要注意事件可能不触发(尤其在后台标签页或低功耗模式下) - 建议只在用户明确进入“省电场景”时才启用降级样式,例如:
if (battery.level <= 0.2 && battery.charging === false) - 避免高频操作 DOM:用单个
document.documentElement.classList.toggle('low-power', isLowPower)控制根类,CSS 内部用.low-power .chart { display: none; }批量降级
移动端特别要注意的兼容性陷阱
在 iOS 和部分安卓定制系统上,以下问题几乎必然出现:
立即学习“前端免费学习笔记(深入)”;
-
navigator.getBattery()在 Safari 中始终返回Promise.reject(),iOS 从不提供该接口 - Android WebView(尤其旧版)可能返回固定值
level: 1或完全不触发levelchange - 后台标签页中,电池事件会被系统节流甚至暂停,导致样式滞后或失效
- 不要依赖
battery.dischargingTime—— 多数设备返回Infinity或NaN,不可用于判断
真正能落地的方案,是把电池状态当作一个弱信号:有则用,无则跳过,绝不阻塞主流程。样式降级逻辑必须自带 fallback,比如默认隐藏高耗组件,仅在确认设备“电量充足且支持 JS 控制”时才展开。否则,你写的 .low-power 类,可能永远等不到被加上去的那一刻。


















