必须用 CSS 变量绑定 filter 实现亮度动态更新:在 :root 定义 --img-brightness: 1,在 [data-theme="dark"] 中覆盖为 0.85,图片通过 filter: brightness(var(--img-brightness)) 响应主题切换,避免硬编码导致失效。

图片在暗黑模式下太刺眼,不是 filter 失效,而是 brightness 值没随主题动态更新——必须用 CSS 变量绑定 filter,否则切主题时亮度卡死在旧值。
为什么直接写 brightness(0.7) 会导致暗黑模式失效
硬编码数值(如 brightness(0.7))在亮色模式下会让图片发灰,切到暗黑模式又可能过暗;更关键的是,它完全不响应 data-theme 切换或 prefers-color-scheme 变化。浏览器不会重新计算这个固定值,哪怕你改了 class 或媒体查询生效了,filter 仍维持原样。
-
brightness()是无单位函数,但它的参数必须是数字或百分比(如0.85或85%),不能是字符串或无单位整数 - 变量必须定义为带语义的 CSS 自定义属性,例如
--img-brightness,且在不同上下文中被覆盖 - 如果只在
:root定义一次,[data-theme="dark"]下不重定义,变量值永远不会变
如何用 :root 和 [data-theme="dark"] 同步控制亮度变量
靠 CSS 层叠优先级:默认走 :root,暗黑模式靠更具体的选择器覆盖变量,filter 自动重算。注意顺序和作用域,别漏掉根元素层级。
- 在
:root中定义默认值:--img-brightness: 1; - 在
[data-theme="dark"]中覆盖:--img-brightness: 0.85;(实测较安全的起点,比0.7更耐看) - 图片元素统一加
style="filter: brightness(var(--img-brightness));"或写进 class,不要在[data-theme="dark"] img里直接写filter—— 那样 JS 动态改变量就无效了 - 别用
filter: contrast()或saturate()替代亮度,它们不解决明暗感知问题
filter: brightness() 的取值陷阱与容错建议
brightness(0.5) 不是“看起来柔和”,而是减半亮度——人眼在暗背景下对暗部敏感,过低数值会让细节塌陷、发脏,反而显得“闷亮”。安全范围比直觉窄得多。
立即学习“前端免费学习笔记(深入)”;
- 亮色模式推荐用
1(原始亮度),暗黑模式推荐0.8–0.9,极少情况低于0.75 -
brightness(0)或负值不被规范支持,部分浏览器静默忽略,不要用 - 如果图片本身偏暗(如夜景图),暗黑模式可设为
1,甚至微调contrast(1.05)提升层次,而非一味压亮度 - 所有场景都别忘了加
will-change: filter(仅当频繁动画时),否则 iOS Safari 可能闪烁
背景图、<img>、SVG 图片的滤镜写法区别
三者不能混用同一套写法:背景图不支持 background-filter(Safari 16+ 才实验性支持),所以必须靠容器 filter;而 <img> 和 SVG <image> 可直接受控,但 SVG 需注意坐标系影响。
-
<img>:加 class 如themed-img,CSS 写.themed-img { filter: brightness(var(--img-brightness)); } - 背景图:给父容器加 class,再用
filter(不是background-filter),因为后者兼容性差 - SVG 中的
<image href="">:需在<image>元素上设filter,并确保preserveAspectRatio不拉伸,否则滤镜形变
最易被忽略的一点:变量名必须语义化且全局唯一,比如 --img-brightness,而不是 --brightness——后者容易被其他模块(如按钮悬停、文字高亮)意外覆盖,导致图片亮度突变或归零。


















