63

CSS :not伪类可能错误的认识

 4 years ago
source link: https://www.tuicool.com/articles/JbmYbe3
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

byzhangxinxu from https://www.zhangxinxu.com/wordpress/?p=8808

本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

一、特别的你,特别的0优先级

fuiaeqe.jpg!webCSS :not伪类常见错误认知之一就是搞不清楚其优先级。

如果对所有CSS伪类的优先级(也就是我们常说的选择器权重)进行分类,你会发现总共只有两个级别, 0 级和 10 级 ① 。

① 0级指没有优先级,1级是标签选择器,10级是类选择器,属性选择器,100级是ID选择器。

伪类,伪类,既然带有“类”字,自然其优先级好类选择器一致。

但是,其中有个特殊,那就是逻辑伪类的优先级都是 0 。例如: :not():is():where() 等。

逻辑伪类整个选择器语句的优先级是由括号里面内容决定的,不同的逻辑伪类规则不一样,其中 :not() 伪类的本身没有优先级,最终优先级是由括号里面的选择器决定的。

例如:

:not(.disabled) {}    /* 优先级等同于.disabled选择器 */
:not(a) {}    /* 优先级等同于a选择器 */

二、生的早,不支持复杂选择器

:not() 逻辑伪类出身很早,早到IE9浏览器都支持,不像现在的新出来的逻辑选择器, :not() 伪类括号里面并不支持复杂的选择器 (虽然新的规范已经让支持了,目前还没有浏览器跟进)。

例如, :not() 伪类括号里面不能多个选择器:

:not(.disabled, .read-only) {}    /* 无效,不支持 */

需要写作:

:not(.disabled), :not(.read-only) {}

例如, :not() 伪类括号里面不支持选择器级联:

:not(a.disabled) {}    /* 无效,不支持 */

需要写作:

:not(a):not(.disabled) {}

三、容易搞不清楚的否定逻辑关系

这是本文的重点。

1. 连续否定的逻辑错误

例如,如果我们想要匹配既不包含 .disabled 类名,又不包含 .read-only 类名的 <input> 元素,我们的选择器该如何书写,很多人会使用下面的CSS代码:

input:not(.disabled),
input:not(.read-only) {}

乍一看好像没问题,实际上,上面的书写是大大的错误。

逗号分隔的选择器,表示的是“或”的关系,而不是“与”的关系。因此 input:not(.disabled), input:not(.read-only) 表示的含义是:不包含 .disabled 类名的 <input> 元素,或者不包含 .read-only 类名的 <input> 元素。

最后导致的结果是 .disabled 类名和 .read-only 类名元素都会匹配。

例如:

<!-- 均会匹配 -->
<input class="disabled">
<input class="read-only">

因为 <input class="disabled"> 虽然不会匹配input:not(.disabled),但是会匹配 input:not(.read-only) ,导致出现了不希望出现的匹配效果。

这里,正确的书写方法应该是:

/* 正确的书写 */
input:not(.disabled):not(.read-only) {}

2. 全局否定的逻辑错误

例如我们希望除了 <article> 标签下的 <p> 元素的 margin 值都是 0 ,我们代码该怎么写。

很多人会这样书写:

:not(article) p {
    margin: 0;
}

看上去没有问题,实际上问题非常严重, :not(article) p 实际语义是,如果 <p> 元素的祖先元素的标签名不是 article ,则 margin 值是 0

其中就包括这样的场景:

<article>
    <section>
        <p>margin此时也是0!<p>
    </section>
</article>

此时,虽然 <p> 元素在 <article> 元素内,但是,由于同时也在 <section> 元素内,于是匹配了 :not(article) p 这个选择器,导致出现意料之外的样式表现。

正确的书写应该是:

p {
    margin: 0;
}
article p {
    margin: 1em 0;
}

咦?不能使用 :not 伪类实现吗?对的,在这种场景下, :not 伪类是无解的。

除非强制层级元素,也就是 <p> 元素是 <article> 的相邻子元素元素,此时我们可以使用下面CSS满足我们需求,不过限制很大,建议还是使用传统重置策略:

:not(article) > p {
    margin: 0;
}

四、最后小结一下下

:not 伪类是目前唯一一个可以大规模放心使用的逻辑伪类,非常有用,优点也很突出,大家可以多用用。

但是,其中也不乏一些会让人踩坑的地方,本文就介绍这几个大家可能会理解错误或使用错误的地方,至于其优点在那里,限于不是本文重点,以后有机会在详细介绍,总之,好用,大家要多用用。

好了,就说这么多。

小朋友又生病了,连续去了3天医院了,待会儿还要去医院挂水,不扯了,感谢阅读,欢迎分享。

ERvaeuu.png!web

本文为原创文章,欢迎分享,勿全文转载,如果内容你实在喜欢,可以加入收藏夹,永不过期,而且还会及时更新知识点以及修正错误,阅读体验也更好。

本文地址: https://www.zhangxinxu.com/wordpress/?p=8808

(本篇完)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK