按钮点击切换CSS滤镜需用JavaScript直接设置document.documentElement.style.filter,初始为none,护眼模式启用时设invert(90%) hue-rotate(180deg) contrast(85%),同步更新localStorage状态与按钮文案,优先兼容iOS 15.4+,旧版Safari建议简化滤镜组合。

按钮点击后如何切换CSS滤镜值
核心是用 JavaScript 动态修改 document.documentElement 或 body 的 style.filter,而不是靠 class 切换——因为滤镜叠加行为不可预测(比如两次 invert(100%) 会抵消),直接赋值更可控。
- 推荐统一作用在
html元素上,避免子元素 filter 被局部覆盖 - 初始状态建议设为
none,护眼模式启用时设为invert(90%) hue-rotate(180deg) contrast(85%)(这个组合对多数屏幕阅读友好,且比纯 invert 更柔和) - 不要用
filter: invert(100%)单独生效,会导致图片/图标完全反色,文字可读但视觉割裂
如何让按钮状态与滤镜同步更新
按钮文字或图标需反映当前模式,否则用户无法确认是否生效。不能只靠 JS 切换 filter 就完事,必须同步维护一个状态标记。
- 用布尔变量
isNightMode或 localStorage 里的eyeProtectionEnabled记录开关状态 - 点击按钮时先取反状态,再更新
document.documentElement.style.filter和按钮 innerText(例如从「开启护眼」变成「关闭护眼」) - 页面加载时读取 localStorage 并初始化 filter 和按钮文案,否则刷新后状态丢失
为什么 localStorage 比 sessionStorage 更合适
护眼模式是用户偏好,不是临时会话设置。用 sessionStorage 会导致关掉浏览器再打开就恢复原样,违背“一键记住”的预期。
-
localStorage.setItem('eyeProtectionEnabled', 'true')写入后,下次访问仍有效 - 注意字符串值判断:读取时用
localStorage.getItem('eyeProtectionEnabled') === 'true',别直接当布尔用 - 如果用户手动清空 localStorage,滤镜会退回到默认关闭状态,这是合理回退,无需额外兜底
移动端 Safari 的 filter 兼容性坑
iOS 15.4+ 支持 filter,但旧版 Safari(尤其 iOS 13–14)对 hue-rotate 和多层 filter 组合支持不稳定,可能卡顿或不渲染。
立即学习“前端免费学习笔记(深入)”;
- 实测安全写法:只用
invert(90%) contrast(90%),去掉hue-rotate可兼容到 iOS 13 - 可通过
if ('filter' in document.documentElement.style)做基础检测,但别依赖它判断是否启用——现代设备基本都支持 - 真机测试比模拟器重要:iOS 模拟器常误报 filter 生效,务必在 iPhone 实机验证滚动和动画是否卡顿



















