一、逻辑伪类选择器及使用场景介绍
1、选择器的作用
CSS 选择器通常用于锁定某个元素为其赋予特殊样式,比如:
- 找到列表中第一项使其高亮
- 为表格单数行增加背景色
但实际业务场景往往更加复杂,比如:想要当输入框聚焦时令所在容器(父元素)边框高亮、对于想要通过 .flex 覆盖 .ant-tab-tabpanel.active 的样式因优先级不够而无效,至少得用 .flex.ant-tab-tabpanel 还得放在 .ant-tab-tabpanel.active 之后才会生效等问题。其实 CSS 早已提供诸如 :has、:is、:where、:not等逻辑组合伪类以供使用,了解它们将大有裨益。
2、父类选择器 :has()
针对上述“想要当输入框聚焦时令所在容器(父元素)边框高亮”的问题,过去找遍所有选择器都不知道该如何实现,最终只得利用 js 来完成功能。:has() 提供一种针对引用元素选择父元素或者先前兄弟元素的方法。比如:
上述“想要当输入框聚焦时令所在容器(父元素)边框高亮”的问题,就可以通过如下 CSS 实现
如果 h1~h3 后面有 h2~h4 兄弟元素,则减少 h1~h3 的下外边距
3、:has()的兼容性问题
由于 :has() 在Chrome105才开始支持,对于较低版本的Chrome浏览器存在兼容问题,但正如前文介绍时所说,CSS选择器中并没有可以替代它的选择器。但是可以调整元素结构实现类似效果:把兄弟元素作为祖先元素使用,通常认为祖先元素包裹子元素,因此当兄弟元素表现包裹该元素,就模拟出祖先元素的效果。
下面结合实际场景举例:
案例:单元格标红校验,若存在.cell-error-show类名就给该单元格边框标红
解决方法一:利用:has()
解决方法二
为 div.cell-error 元素后增加一个兄弟元素 div.cell-error-box,当 div.cell-error.cell-error-show 因单元格校验失败而出现时,通过兄弟元素选择器令 div.cell-error-box 模拟实现父元素单元格被选中的效果,样式实现如下
4、:is() / :where()
这两个伪类的作用类似,最大的用处是使代码更加简洁。表示匹配到该伪类中任何一个选择器,例如
利用 :is() 可以简写为如下
利用 :where() 可以简写为如下
而 :where() 与 :is() 的区别在于 :where() 的优先级总是为 0,但是 :is() 的优先级是由它的选择器列表中优先级最高的选择器决定的。如下示例中 footer a 只能覆盖 :where() 选择器下的 a 元素,而不能覆盖 :is() 选择器下的 a 元素
5、否定伪类 :not()
:not() 接收一个或多个以逗号分隔的选择器作为参数,若当前元素与括号中选择器不匹配则匹配到该伪类选择器。:not() 本身没有优先级,不会推高样式优先级。例如
而采用 :not() 后如下
对于样式优先级,应优先考虑灵活利用选择器避免推高优先级,因为高优先级样式只能被更高优先级样式覆盖,而为了构造更高优先级样式将降低样式灵活性、增加样式复杂度。特别注意避免不必要的 !important(就好比斗地主,别人出个3,你直接上王炸),而通过属性选择器等精准匹配元素。
二、CSS 变量
CSS 变量实际指 CSS变量函数var() 和 CSS自定义属性 的统称。它为 CSS 语言带来了质的提升,包括三个方面:
- 降低开发和维护成本。如网站主题风格的切换实现、原本要全局替换的值现在只需要修改自定义属性一处地方。
- 改变图形交互效果实现中 JS 与 CSS 所占的比重。一些传统需要 JS 操作 DOM 的处理方式完全可以借由 CSS 实现,不用操作DOM了,性能上自然也就提升了。
1、CSS 变量语法使用示例
2、CSS 自定义属性命名
支持数值、中划线、空格、中文。
不支持 $、[、]、^、(、)、%、" 等特殊字符,需要用反斜杠转义。
3、CSS 自定义属性使用
3.1、在 CSS 中使用
自定义属性的作用域不是全局,在子元素上定义的自定义属性无法在其父元素上访问到,反之在父元素上定义的属性可以在子元素上获取到。而如果想要全局都能访问到的自定义属性,可以定义在 :root 上。
3.2、在 HTML 中使用
在 HTML 上的自定义属性可以在其子元素上访问到
3.3、在 JavaScript 中使用
通过 dom.style.setProperty 设置自定义属性,通过 getComputedStyle(dom).getPropertyValue 获取自定义属性