先看个效果
默认模式:
护眼模式:
对于需要长时间盯着屏幕同学,后面这个“护眼模式”相对“默认模式”的亮底,应该算是更舒适、不那么容易引起视觉疲劳的一个选择。
在当下,作为Web前端开发者,要在网页上添加这么个护眼模式,其实可能并不需要定制化的去针对暗色调写一套完整皮肤样式。
最简单的护眼实现代码
要在任意网站启用上图的“护眼模式”,其实你只需要打开浏览器控制台,执行以下代码就可以了:
const cssEl = document.createElement('style')
cssEl.innerHTML = `
html.cye-enabled {
filter: contrast(0.96) brightness(0.9) invert(1);
}
html.cye-enabled img {
filter: brightness(0.9) invert(1);
}
`;
document.head.appendChild(cssEl);
document.documentElement.classList.add('cye-enabled');
很简单对不对。
其实就是给 documentElement 添加一个样式类,相应的,也就是添加个反色滤镜(让亮色变成暗色)。
不想让img图片变成反色而导致肉眼无法识别,则可以再通过滤镜反转回来。
让是否开启“护眼模式”可控
配合离线存储,记住用户设置
支持微调亮度对比度(修改文档流上下文的CSS规则)
如何监听系统主题色调变化
不带UI的,“完整”效果代码
可以复制以下代码到浏览器控制台执行,然后通过 window.setCyeFilter(enabled, contrast, brightness)
设置护眼模式开关方式、对比度、亮度。
(() => {
const cssEl = document.createElement('style')
cssEl.innerHTML = `
html.cye-enabled {
background: #fff; /* 如果有自己的背景色,那么去掉这行 */
filter: contrast(0.96) brightness(0.9) invert(1);
}
html.cye-enabled img {
filter: brightness(0.9) invert(1);
}
html.cye-enabled body {
filter: none !important; /* 防止三方浏览器插件等重复的护眼样式生效 */
}
`;
document.head.appendChild(cssEl);
// document.documentElement.classList.add('cye-enabled');
/***** 一些JS设置逻辑 ****/
// 护眼模式
const getLV = (k) => JSON.parse(localStorage.getItem(k));
const setLV = (k, v) => localStorage.setItem(k, JSON.stringify(v));
let cyeMediaQueryList = null;
try {
cyeMediaQueryList = window.matchMedia('(prefers-color-scheme: dark)');
cyeMediaQueryList.addListener(setDocCyeByLS); // 通过浏览器API监听系统层面的主题模式配置变换
} catch(e) {
console.warn('当前环境可能不支持 matchMedia');
}
window.setCyeFilter = (enabled, contrast, brightness) => {
setLV('cyeEnabled', enabled); // true 开启护眼模式,false 关闭护眼模式,2 跟随系统主题是否黑暗模式动态设定
setLV('cyeContrast', contrast); // 对比度,可微调视觉效果
setLV('cyeBrightness', brightness); // 亮度,可微调视觉效果
// 护眼模式为“开启”或“跟随系统”且系统是开启的
const isOpen = enabled === true || (enabled == 2 && cyeMediaQueryList && cyeMediaQueryList.matches);
const { classList } = document.documentElement || {};
classList && classList[isOpen ? 'add' : 'remove']('cye-enabled');
if (!isOpen) return;
const sss = document.styleSheets;
if (!sss) return;
let csss = null;
for (let i = 0; i < sss.length; i++) {
const cssi = sss[i];
if (cssi && cssi.ownerNode && cssi.ownerNode.id == 'ghdef') {
csss = cssi;
break;
}
}
if (!csss) return;
const ruls = csss.rules;
if (!ruls) return;
let clsObj = null;
for (let j = 0; j < ruls.length; j++) {
const rulj = ruls[j];
if (rulj && rulj.selectorText === 'html.cye-enabled') {
clsObj = rulj;
break;
}
}
if (!clsObj) return;
clsObj.style.filter = 'contrast(' + contrast + ') brightness(' + brightness + ') invert(1)';
return true;
};
// 根据本地存储,判断是否开启护眼模式
function setDocCyeByLS() {
setCyeFilter(
getLV('cyeEnabled'),
getLV('cyeContrast') || 0.96,
getLV('cyeBrightness') || 0.9
);
};
setDocCyeByLS();
})()
CSS中的其他可用方案
mix-blend-mode: difference
https://blog.csdn.net/weixin_44733660/article/details/121958062
Comments
可以发邮件 huzunjie@pyzy.net 或移步到 https://github.com/huzunjie/blog.pyzy.net/issues 评论交流。