护眼模式应通过 :root 定义 --bg-primary 等CSS变量并全局继承,而非仅改 body 背景或用 ::before 伪元素覆盖;推荐米黄区间 #f7f5f0(RGB差值<10),统一用 html.eye-care 控制,兼顾系统偏好与手动切换。

用 :root 配合 background-color 实现可切换的浅色护眼基底
直接改 body 背景容易被子元素的 background 覆盖,真正起效的是把颜色定义在 CSS 自定义属性里,再让所有容器默认继承。护眼模式本质不是“加一层”,而是“换一套基础色值”。
- 把米黄色(如
#f8f5f0)设为--bg-primary,正文文字用深灰(#333)而非纯黑,提升对比度舒适性 - 所有带背景的组件(
div、section、card等)默认写成background-color: var(--bg-primary);,而不是硬编码#fff - 避免只改
body:很多 UI 框架或组件自带白色背景,不统一接管就会出现“白底上浮一块米黄”的割裂感
用 ::before 伪元素叠加半透明米黄层的适用场景和风险
这种方式看似简单,实则属于“表面覆盖”,适合临时调试或极简页面,但对真实项目多数时候是负优化。
- 必须给
html或body加position: relative,否则::before无法全屏定位 - 伪元素层级(
z-index)必须设为负值(如-1),否则会遮挡所有点击和滚动 - 半透明叠加(如
rgba(248, 245, 240, 0.7))会让图片、阴影、渐变失真——特别是box-shadow会变浑浊,SVG 图标边缘发虚 - 滚动时伪元素可能闪烁(尤其 Safari),因为浏览器对
fixed或absolute全屏伪元素的合成策略不稳定
prefers-color-scheme 与手动切换共存时的 class 冲突问题
用户开了系统浅色模式,又点网页上的“护眼模式”开关,两个信号打架,CSS 优先级容易失控。
- 别用
@media (prefers-color-scheme: light)直接写背景色,它会被后续 JS 添加的class="eye-care"覆盖或忽略 - 推荐统一收口到一个 class:比如始终用
html.eye-care控制护眼色值,系统偏好只作为初始化依据(JS 读取后自动加 class) - 如果用
data-theme="eye-care",记得所有相关 CSS 规则都带上该属性选择器,例如html[data-theme="eye-care"] { --bg-primary: #f8f5f0; } - Vue/React 组件内联样式或 CSS-in-JS 容易绕过全局 class,需额外检查
style属性是否硬写了background
RGB 值微调比“米黄”更关键:避开泛黄、发灰、刺眼三个坑
很多人照搬网上搜的“护眼色值”,结果发现越调越累眼。真正影响舒适度的是 RGB 三通道的相对强度和亮度落差。
立即学习“前端免费学习笔记(深入)”;
- 避免
R过高(如#fff8e1):偏橙黄,长时间阅读引发视觉疲劳 - 避免
G和B过低(如#f5f5dc):接近米白但缺绿蓝,屏幕观感发闷、像蒙灰 - 推荐区间:
R: 245–249,G: 243–247,B: 238–242(例:#f7f5f0),亮度均匀,无明显色偏 - 务必在真机+不同亮度下预览:同一色值在 OLED 和 LCD 上温感差异极大,MacBook 的 P3 色域还会让米黄变粉
护眼模式不是颜色越暖越好,而是让眼睛在长时间注视时不触发额外的色适应调节——这点常被当成玄学,其实就藏在 RGB 差值小于 10 这个细节里。










