暗黑模式图片适配研究
正常、暗黑模式切换时,如何保证图片展示效果最佳
Since dark mode starts to be of fashion on main cellphones, the dark mode for page is coming too.
如何动态检测暗黑模式的切换呢?
1. window.matchMedia
可以满足需求
if (window.matchMedia) {
const matches: MediaQueryList = window.matchMedia(
'(prefers-color-scheme: dark)'
)
const func = (obj: MediaQueryListEvent): void => {
const evt: EventTarget =
obj.currentTarget ||
obj.target ||
obj.srcElement ||
new EventTarget()
const mql: MediaQueryList = <MediaQueryList>evt
document.body.classList[mql.matches ? 'add' : 'remove'](
'codernote_dark'
)
}
if (matches) {
if (matches.addEventListener) {
matches.addEventListener('change', func)
} else if (matches.addListener) {
matches.addListener(func)
} else {
matches.onchange = func
}
}
} else {
console.log('detection is not supported')
}
2. 使用 css 有媒体查询来满足
// first put normal style here
// ...
body {
color: darkblue;
}
@media screen and (prefers-color-scheme: dark) {
// write some darkmode style here
// ..
body {
color: darkgreen;
}
}
3. 如果是不同模式下图片也要跟着变呢?
分两种情况
- 图片在编写 css 时是确定的(这种情况好处理)
- 图片是动态返回的
1. 针对图片是确定的,如普通模式是白底黑色线条,这种通过上述的 css 媒体查询可以做到,示例如下
.some-img-helder {
width: 100px;
height: 100px;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
background-image: url('./point_to_nomal_img_path.png');
}
// 暗黑模式匹配
@media screen and (prefers-color-scheme: dark) {
.some-img-helder {
background-image: url('./point_to_dark_mode_img_path.png');
}
}
这里为什么用 background-image来做,而不是 img,
主要考虑是 background 方式不影响 dom ready,能让页面结构尽快展示出来
如果用图片是动态返回的,那么可以使用第二种方式来实现,当然已知确定图片的也可以使用这种方式:
2.图片是动态返回的
.img_wrap {
img {
width: 100px;
height: 100px;
}
.normal {
display: inherit;
}
.dark {
display: none;
}
}
@media screen and (prefers-color-scheme: dark) {
.img_wrap {
.normal {
display: none;
}
.dark {
display: inherit;
}
}
}
<div class="img_wrap">
<img class="normal" src="point_to_nomal_img_path.png" />
<img class="dark" src="point_to_dark_mode_img_path.png" />
</div>
这样做是基于以下原因:
- 相同规则的 css 后边的优先级更高
- 虽然两张图片都设置了 src, 但 display: none 不会加载图片,和只有一张图片效果一致
- 媒体查询只有在满足条件时,内部的规则才会生效
- 第二种方式同样适用于自行切换主题的场景,实现方式为把 img_wrap上追加一个主题样式名,然后在后面补充主题样式包裹下的样式即可,示例如下:
.img_wrap {
color: black;
background-color: white;
img {
width: 100px;
height: 100px;
background-repeat: no-repeat;
background-size: 100%;
background-position: center;
}
}
.img_wrap.yellow_theme {
color: white;
background-color: lightgoldenrodyellow;
}
<div class="img_wrap yellow_theme">
<div>文本内容</div>
<img src="动态返回图片" />
</div>