Open
Description
在进行响应式网页开发时,利用@media screen
设置屏幕断点是十分常用的做法:
@media screen and (max-width: 768px) {
/* your style */
}
@media screen
可以判断当前设备的宽度然后使用定义的样式。
但是@media screen
只能控制样式,不能控制逻辑。
假如现在有这么一个需求:在屏幕宽度小于768px时,出现弹框。
最常规的做法是用js检测屏幕:
window.onresize = function() {
if(window.document.documentElement.clientWidth <= 768) {
alert(window.document.documentElement.clientWidth);
}
};
可以看到当收缩视口时,会触发弹窗。
但是window.document.documentElement.clientWidth
是一个不稳定的属性,他会受到padding,margin,和border以及浏览器设置的影响,有时候并不能精确地获取屏幕宽度的值。而且这种方法的可维护性很差,会造成JS和css的耦合严重,当css断点要改动时js也要一同改动。
那么现在看起来判断屏幕断点的方法最好还是css,但是怎么样能够让css到达断点时通知js呢?用伪类做中介是一个完美的方法。
css通过伪类与js交互
具体的思路是我们用@media query
来动态改变某个元素的伪类,然后用js来获取这个元素的伪类的content
,然后js根据获取到内容得到当前屏幕的断点。
首先我们在css设置三个屏幕断点:
@media screen and (max-width: 768px) {
}
@media screen and (max-width: 1024px) and (min-width: 768px){
}
@media screen and (max-width: 1200px) and (min-width: 1024px) {
}
然后我们用@media query
动态地改变body
的after
:
body::after {
content: '';
display: none;
}
@media screen and (max-width: 768px) {
body::after {
content: 'small';
}
}
@media screen and (max-width: 1024px) and (min-width: 768px){
body::after {
content: 'middle';
}
}
@media screen and (max-width: 1200px) and (min-width: 1024px) {
body::after {
content: 'large';
}
}
最后我们用js获取body
的after
的content
里面的值:
const content = window.getComputedStyle(document.body, ":after").getPropertyValue("content");
if(content.indexOf('small') > -1) {
//小屏幕
}
if(content.indexOf('middle') > -1) {
//中等屏幕
}
if(content.indexOf('large') > -1) {
//大屏幕
}
之所以上面要用indexOf
而不是直接===
是因为在某些浏览器下面用js获取到的content
会包含双引号(比如会得到"small"
而不是small
)。
小试牛刀
然后现在我们试一试用这种方法来解决一开始提出的问题:在特定的断点弹窗。
不用改动很多东西,只要在js的判断里面加要的东西就行,简单直接,耦合成度也不高,然后为了更加直观到的效果我把它套进了onresize
方法里面:
window.onresize = function() {
const content = window.getComputedStyle(document.body, ":after").getPropertyValue("content");
console.log(content);
if(content.indexOf('small') > -1) {
alert(content);
}
if(content.indexOf('middle') > -1) {
alert(content);
}
if(content.indexOf('large') > -1) {
alert(content);
}
}
效果自然是棒棒哒。