这篇文章发布于 2020年02月13日,星期四,17:35,归类于 CSS相关, JS实例。 阅读 31311 次, 今日 22 次 18 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=9263
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。
一、需要通过CSS传参的背景
CSS中有很多媒体查询的用法,例如设备尺寸判别,是否支持鼠标行为,是否是黑暗模式,是否是省电模式等。
比方说最近经常提到的黑暗模式,深色主题:
@media (prefers-color-scheme: dark) { /* 黑暗模式,深色主题 */ } @media (prefers-color-scheme: light) { /* 浅色主题 */ }
CSS可以自动检测,但是有时候,在JS中,我们也需要根据不同的系统主题,然后实现不同的交互逻辑,或者渲染出不一样的内容。
怎么办?似乎一时间也找不到现成的JS API来检测系统模式,只能借助于CSS中传参了。这就是一个典型的场景,类似的场景还有很多。
更新于2020-02-26
媒体查询有JS API检测,为window.matchMedia()
,IE10+浏览器支持。
例如:
1. CSS和JS边界宽度一致性
我们在做响应式布局的时候,经常会需要设定一个临界宽度值,例如当设备的宽度小于640像素的时候,我们就认为是进入了移动端;或者是宽度小于480的像素的时候,就使用移动端布局等。
此时,JavaScript代码也需要根据这个临界宽度实现不同的交互效果,大于多少的时候是PC的交互,小于多少的时候是移动端布局下的交互。
很多人在实际开发的时候就CSS代码和JS代码约定一下,例如:
@media screen and (max-width: 480px) {
/* 小屏幕宽度下的响应式布局 */
}
if (screen.width < 480) {
/* 小屏幕宽度下的交互行为 */
}
要是这种约定会有一个问题,等项目过了一段时间之后,发现这个临界宽度有问题,比方说手机横屏的时候,它的宽度是大于480px
的,也应该是移动端的布局方式,于是开发就改成了640px
。
@media screen and (max-width: 640px) {
/* 小屏幕宽度下的响应式布局 */
}
结果忘记JS代码中也有这一茬判断,结果就会出现bug。
如果原先实现的时候,我们的JavaScript代码中的屏幕判断是基于CSS传参的话,那就不会有这样子的维护问题出现。
2. 浏览器是否支持:hover伪类交互
我们会开发一些ui组件,希望在桌面端和移动端,以及物联网设备上通用。
有些组件在桌面当我们使用mouseenter
或者mouseover
事件来实现体验还是很不错的,非常便捷。但是如果这些东西用在移动端以及其他一些触屏设备上,则这个世界就有问题啊,因为没有这种hover的说法。
好在CSS代码中是有关于浏览器是否支持:hover伪类交互媒体查询判断(此查询有专门文章介绍,点击这里):
@media (any-hover: none) {
/* 设备不支持hover事件 */
}
可惜JS中并没有这样的API直接判断。很多人应该是通过判断浏览器是否支持touchstart
之类的事件来进行判断的。不过可惜这种判断方法是不准确的。因为很多触摸设备也是可以连接鼠标设备的,此时hover事件也应该被良好支持。
因此,最后的方法还是通过CSS媒体查询判断,然后把这个判断结果以参数形式传递给js。
好啦,下面问题来了,上面举了这三个案例,我们如何通过CSS把我们的参数传递给JS代码呢?
二、CSS传参给JS的方法
通常借助CSS向JS传参,我都是使用下面这两种方法。
1. content伪元素内容传参
例如:
@media (any-hover: none) { body::before { content: 'hoverNone'; display: none; } }
此时就可以通过JS代码获取body伪元素传递的信息是什么了:
var strContent = getComputedStyle(document.body, '::before').content;
// strContent结果是'none'则表示支持hover
// strContent结果是'"hoverNone"'则表示不支持hover经过,需要换成click事件
本文就预埋了上面这样的CSS代码,因此,Chrome浏览器下,打开控制台,进入移动端预览模式,输入JS测试下,可以看到我们CSS传递的字符串信息被JS获取到了。
此时,我们就可以根据::before
, ::after
伪元素配合content
属性,获知CSS中传递的信息了。
这种传参方式的优点在于兼容性相对较好,但是不足却也很明显,那就是我们传递的参数值的数量是有限的,如果我们想一次性传多个值,就有些捉襟见肘,此时可以试试下面这种方法,借助CSS自定义属性。
2. CSS自定义属性(CSS变量)传参
直接上代码,有了CSS自定义属性(CSS变量),黑暗模式和浅色模式的开发和维护工作就变得相对容易很多,除此之外,这个CSS自定义属性我们还可以用来给JS做模式识别。
:root { --mode: 'unknown'; } @media (prefers-color-scheme: dark) { /* 黑暗模式 */ :root { --mode: 'dark'; --colorLink: #bfdbff; --colorMark: #cc0000; --colorText: #ffffff; --colorLight: #777777; } } @media (prefers-color-scheme: light) { /* 浅色主题 */ :root { --mode: 'light'; --colorLink: #34538b; --colorMark: #cc0000; --colorText: #000000; --colorLight: #cccccc; } }
JS检测代码:
var mode = getComputedStyle(document.documentElement).getPropertyValue('--mode').trim();
// mode结果是'"dark"'则表示黑夜主题,深色模式,黑暗风格,护眼模式。
// mode结果是其他表示默认模式
例如在我这个电脑上运行的结果是下图这个:
在Mac OS X或者移动端设备上应该会显示其他的值,欢迎帮忙测试截个图发我,我更新到文章中。
使用CSS自定义属性传统的好处是非常灵活,我们可以定义很多很多的变量都可以。而且其实我们也没有任何必要担心兼容性的问题。为什么呢?因为凡是支持黑夜模式的设备浏览器,一定支持CSS自定义属性。
因此,综合来看,使用CSS自定义属性传参在黑暗模式这个场景中是最佳的实现。但是,如果是基于设备宽度传参响应式布局这场场景,还是使用CSS content
属性传参为佳。
三、结束语
最近出疫情,算一算,公司鱼缸里面的小鱼3周没有喂食了,现在水位估计只有5~6成,不饿死也冻死了,唉,还是同事送的漂亮小鱼呢,不知道下周能不能复工,祈祷可以复工去上班。
偏远山区的蝙蝠煽动了下翅膀,我公司鱼缸里的小鱼饿死了。
真是世事难料。
唉,其他没什么好说的了。
欢迎转发,欢迎分享。
本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=9263
(本篇完)
- 你不知道的CSS media查询与用户体验 (0.543)
- CSS any-hover any-pointer media查询与交互体验提升 (0.391)
- 几行CSS让整站支持深色模式的探索与拓展 (0.243)
- CSS变量对JS交互组件开发带来的提升与变革 (0.177)
- Polyfill吊炸天的CSS attr()新语法 (0.177)
- 巧借CSS var变量实现任意的CSS自定义语法 (0.177)
- 介绍一种CSS变量未定义语法也OK的小妙招 (0.177)
- 小tips:了解CSS变量var (0.139)
- 如何让MP4 video视频背景色变成透明? (0.122)
- 深入理解CSS mix-blend-mode滤色screen混合模式 (0.122)
- 纯CSS实现未读消息超过100自动显示为99+ (RANDOM - 0.104)
感觉直接读写自定义的 data-theme-class 更方便一些吧
css dark theme checker demo
https://codepen.io/xgqfrms/pen/GRprYLm
JS向CSS传参有什么好的办法呢,需要兼容IE10+
在 JS 中用 window.matchMedia() 虽然可以查,但还是等于 @media 要在 CSS 和 JS 中分别写一次,改代码时要改两处,没有解决本文提到的一个重要问题。
写得很好,继续支持你!
我的小鱼,应该已经臭了
我在 MAC 下的谷歌是可以的 但是 Safari 引号被转义了
MacOS 实测是可以的,Windows 应该也支持这个特性吧?难道要使用最新版 chromium?
支持的window 的暗-应用模式
请问大神有没有javascript的相关书籍推荐?在下零基础
学后台吧,后台更容易。
以前就想过这个问题,以为传不了,今天看到了方案,就想说两个字:牛逼!
附上Mac截图:
https://imgkr.cn-bj.ufileos.com/30cd0e07-0aa4-4011-9083-9b664edfa80e.png
需要在echart中适用黑暗模式的适配,怎样使用呀
label: {
normal: {
textStyle: {
color:
}
}
},
模式识别我用的是
window.matchMedia(“(prefers-color-scheme: dark)”)
好像也不错
都有相应的 CSSOM API 啊。
https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia
https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model
你们还没复工啊,我们都上班一周了
在Android的Chrome(79)下能读取是否黑暗模式,WebView下不能读取。
没有ios设备,没有linux设备。
截图已经发给你了
做了个检测用的网址
https://jsbin.com/metovogaja/
Win10 Chrome(80)下可以成功获取黑暗或明亮模式,但是如果在网页浏览中切换模式,js不会自动运行。
我没找到监听”–mode”变量的方法。