逻辑操作符

1. 前言

上一节课我们已经知道了哪些属性可以分辨不同的屏幕设备,并且也知道了程序中的像素为何与手机中的像素不匹配的原因。

那么本小节我们将利用逻辑操作符来结合前两节课讲的那些内容一起试水响应式布局。

2. 逻辑操作符

那么什么是逻辑操作符呢?

逻辑操作符可用于联合构造复杂的媒体查询,您还可以通过用逗号分隔多个媒体查询,将它们组合为一个规则。

逻辑操作符分为以下四种

含义
and 用于将多个媒体查询规则组合成单条媒体查询,当每个查询规则都为真时则该条媒体查询为真,它还用于将媒体功能与媒体类型结合在一起。
not 用于否定媒体查询,如果不满足这个条件则返回true,否则返回false。 如果出现在以逗号分隔的查询列表中,它将仅否定应用了该查询的特定查询。 如果使用not运算符,则还必须指定媒体类型
only 仅在整个查询匹配时才用于应用样式,并且对于防止较早的浏览器应用所选样式很有用。 当不使用only时,旧版本的浏览器会将screen and (max-width: 500px)简单地解释为screen,忽略查询的其余部分,并将其样式应用于所有屏幕。 如果使用only运算符,则还必须指定媒体类型。
, (逗号) 逗号用于将多个媒体查询合并为一个规则。 逗号分隔列表中的每个查询都与其他查询分开处理。 因此,如果列表中的任何查询为true,则整个media语句均返回true。 换句话说,列表的行为类似于逻辑或or运算符。

3. and

看完上面的表格还是有些懵对吧?来看一下语法你就明白到底是怎么回事了:

@media screen {
	div {
		color: black;
	}
}

为了方便大家的学习,上面写了一种最简单的媒体查询规则,其中@media是固定写法,表示创建一个媒体查询,后面跟着的是一个媒体类型,还记得前几节我们学过的那些媒体类型吗?通常咱们只会用到screen这种屏幕类型,然后大括号里面就可以写CSS语句了,你平时怎么写CSS,在大括号里就怎么写,也就是说上面的那几行代码代表的含义是:

当用户使用屏幕设备浏览网页时,页面上的div元素内的字体颜色变为黑色

⚠️不过需要注意的是,@media里面同样需要遵守CSS权重规则,比如后面的覆盖前面的,标签选择器覆盖不了类选择权的样式,所以尽量把@media写在整个CSS文件的末尾。

看懂最简单的语法后,再来加点难度了,比如我们希望字体颜色在手机上是蓝色,但是在电脑上是绿色:

div {
	color: green;
}
@media screen and (max-width: 450px) {
	div {
		color: blue;
	}
}

假设宽度低于450px的设备就是手机设备,@media screen已经声明了屏幕设备,但是如果再加入一条媒体属性(max-width: 450px)的话就需要用and这个逻辑操作符来进行连接,有的同学可能搞不太懂为什么max-width就是小于等于的意思呢?

为了便于理解,咱们把max-width换一个说法,换成max-salary,意思是最高工资,然后min-width换成min-salary最低工资,大家应该都听说过很多城市都有着最低工资的标准吧。

拿北京市举例,目前的最低工资标准为2200元,换句话说你的工资肯定是大于等于(≥)2200元的。用代码写出来就变成了:min-salary: 2200,其实就等同于salary ≥ 2200。如果你理解了最低工资,那么相信你就会理解max-widthmin-width了。

然后再来看代码,咱们将默认样式定义在了最前面,然后把@media定义在了后面,为的就是在规则满足咱们写的条件时,后面的样式能够覆盖掉前面的。

and就相当于并且的意思,@media screen and (max-width: 450px)就可以理解为:当媒体是屏幕设备并且最大宽度为450px时执行后面的代码。

4. not

not这个单词很好理解,看名字就知道是否定的意思,比如我们把刚才的需求反过来,变成字体颜色在手机上是绿色,但是在电脑上是蓝色:

div {
	color: green;
}
@media not screen and (max-width: 450px) {
	div {
		color: blue;
	}
}

这么写看起来不是很好理解对吧,因为翻译成中文就是:不是屏幕设备和最大宽度450,看起来像是不在屏幕设备上生效一样,而实际上not不是仅仅否定跟在它后面的那个单词,而是否定整条语句,相当于:@media not (screen and (max-width: 450px)),这回再翻译成中文:不是(最大宽度为450的屏幕设备),那么超过450px的宽度就已经符合这个条件了。

5. only

only从字面意思去理解是仅仅的意思,那么如果加入它以后:

@media only screen {
	/* 省略若干代码 */
}

翻译成中文是:仅仅只在屏幕设备中生效。

可是咱们之前学的:

@media screen {
	/* 省略若干代码 */
}

不也是只在屏幕设备上生效嘛,那加上这个only又有什么用呢?

实际上这是为了兼容低级浏览器而生的,它是为了在不支持媒体查询的浏览器中隐藏样式表,浏览器处理以only开头的关键词时将会忽略only。

这又是什么意思呢?其实就是在现代浏览器中,你加不加only效果都是一样的。
但在一些非常老旧的浏览器,如果你加了only,它就会直接忽略掉这条语句。

看到这你可能不明白了,为什么要让老版本浏览器忽略掉你写的@media呢?

你可以简单的理解为:老版本浏览器有点近视眼,只看得到@media和紧跟在它后面的一个单词。
在它的眼中,你写的@media only screen and (max-width: 450px)它只看得到@media only
如果你还记得媒体设备的那张表格的话,你应该知道压根儿就没有only这种设备,所以它就会认为你写错了,从而忽略掉这段语句。

但是如果你不加only的话,那么你写的@media screen and (max-width: 450px)在它眼里就会看成@media screen,因为没有看到后面的限制条件,所以你写在@media里面的CSS代码会在 screen 这种设备生效,就相当于在所有屏幕设备(手机、平板、笔记本)这段代码都会生效。

6. 逗号

逗号其实就相当于或者的意思,其实我发现有一小部分人有点搞不清并且或者的区别。这在日常生活中影响可能不大,但是在程序中如果你不能理解并且或者的话可能会导致你的代码出bug。

举个例子,如果想表示一个数(x)大于10、小于0,应该怎么写?会不会写成这样:
10 < x < 0
但其实这么写虽然能看懂,但语法是错的,想让计算机认识你写的代码的话应该写成这样:
x < 0 (或/并) x > 10
你觉得,应该是还是呢?

正确答案是

如果是的话,需要同时满足这两个条件,试问什么数能够既小于0又大于10 呢?

只能尽量的满足这俩条件中的一个,这就叫作。就相当于一个人,你不能让他既高又矮、既胖又瘦吧。

理解了,那么咱们就可以用逗号来写代码了:

div {
	color: green;
}
@media screen and (max-width: 450px), (min-width: 1200px) {
	div {
		color: blue;
	}
}

这回的意思是:字体在平板设备(假设平板设备宽度在450和1200之间)上是绿色,其他设备是蓝色。
这就相当于:x ≤ 450 或 x ≥ 1200,x 就是其他设备。

当然了,其实如果把 x 当成平板设备的话会更合理:
x ≥ 450 并 x ≤ 1200 (450 ≤ x ≤ 1200)

div {
	color: blue;
}
@media screen and (min-width: 450px) and (max-width: 1200px) {
	div {
		color: green;
	}
}

但是咱们之前之所以把平板写成那样是为了给大家演示逗号的写法,大家可以根据自己的业务逻辑来灵活的选择用(and)还是(,)。

7. 思考

为什么要用这么最大宽度(max-width)、最小宽度(min-width)累赘的写法呢?
直接用数学符号大于(>)小于(<)多好啊!既直观,又方便。

其实原因是因为,在 HTML 中,大于号(>)小于号(<)是标签的组成部分,假如你是在 <style> 标签内部写的@media:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>media</title>
  <style>
    @media screen and (450px < width < 1200px) {
    }
  </style>
</head>
<body>
</body>
</html>

解析器可能会搞混各种标签,不知道你是要写标签还是只是一个小于号(还是不够智能啊)。

不过鉴于这种语法既直观又方便,CSS4打算将其纳入标准,但目前还不是使用这种语法的时候。

8. 简写

有时你看别的教程或者别人的代码可能会写成这样:

@media (min-width: 450px) {
	/* 此处省略若干代码 */
}

可以看到@media的后面并没有写任何的媒体类型,而是直接写了一个媒体属性,而且这样的代码也可以生效,那么这是为什么呢?

还记得媒体设备的那张表格吗?

设备 中文含义
all 所有设备
print 用于打印机和打印预览
screen 用于电脑屏幕、平板电脑、智能手机等
speech 应用于屏幕阅读器等发声设备

如果你不写设备,默认就是 all,all 里面当然也包含了 screen 啦,上面的代码就相当于:

@media all and (min-width: 450px) {
	/* 此处省略若干代码 */
}

如果你不是很关心网页在打印设备和发声设备上会是什么样的话,也可以省略媒体类型,反正大部分网页都是要显示在屏幕设备上的。

9. 结束语

看到这里,这门课就算是要结束了,如果你之前没有过移动端网页布局的经验,希望这门课可以帮到你。

不过有的同学可能会有疑惑,同样一个布局你居然写出那么多种实现方式,记不住啊!为什么不只写一种呢?

一方面是有些企业面试就喜欢面试者能够提供各种各样的不同解决方案,以此来考察面试者的技术是否足够全面。

所以我希望这门课可以帮助大家在面试过程中能够脱颖而出,让面试官觉得你的技术相当全面。

另一方面是有时候我们会遇到一些复杂样式的需求,不是咱们课程中的这几种很典型的布局。那么此时就需要你灵活运用各种 CSS 技术来实现复杂布局,可能这个按钮用个左浮动、那个图片用个绝对定位、Window10 菜单样式用个 Grid、外层容器用个 Flex 等:
图片描述
只有能够灵活运用各种各样不同的 CSS 技术才能实现层出不穷的样式需求,只掌握一种方法还是远远不够的。

如果你实在学不动这么多种实现方式,那我建议你把每个章节中的弹性盒子法(Flex)重点练会即可,弹性盒子在移动端布局相当流行,并且功能也十分强大。