日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
淺談邏輯選擇器Is、Where、Not、Has

在 CSS 選擇器家族中,新增這樣一類(lèi)比較新的選擇器 -- 邏輯選擇器,目前共有 4 名成員:

成都創(chuàng)新互聯(lián)專注于臨淄企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,商城網(wǎng)站建設(shè)。臨淄網(wǎng)站建設(shè)公司,為臨淄等地區(qū)提供建站服務(wù)。全流程按需設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

  • :is
  • :where
  • :not
  • :has

本文將帶領(lǐng)大家了解、深入它們。做到學(xué)以致用,寫(xiě)出更現(xiàn)代化的選擇器。

:is 偽類(lèi)選擇器

:is() CSS偽類(lèi)函數(shù)將選擇器列表作為參數(shù),并選擇該列表中任意一個(gè)選擇器可以選擇的元素。

在之前,對(duì)于多個(gè)不同父容器的同個(gè)子元素的一些共性樣式設(shè)置,可能會(huì)出現(xiàn)如下 CSS 代碼:

header p:hover,
main p:hover,
footer p:hover {
color: red;
cursor: pointer;
}

而如今有了 :is() 偽類(lèi),上述代碼可以改寫(xiě)成:

:is(header, main, footer) p:hover {
color: red;
cursor: pointer;
}

它并沒(méi)有實(shí)現(xiàn)某種選擇器的新功能,更像是一種語(yǔ)法糖,類(lèi)似于 JavaScript ES6 中的 Class() 語(yǔ)法,只是對(duì)原有功能的重新封裝設(shè)計(jì),實(shí)現(xiàn)了更容易的表達(dá)一個(gè)操作的語(yǔ)法,簡(jiǎn)化了某些復(fù)雜代碼的寫(xiě)法。

語(yǔ)法糖(syntactic sugar)是指編程語(yǔ)言中可以更容易的表達(dá)一個(gè)操作的語(yǔ)法,它可以使程序員更加容易去使用這門(mén)語(yǔ)言,操作可以變得更加清晰、方便,或者更加符合程序員的編程習(xí)慣。用比較通俗易懂的方式去理解就是,在之前的某個(gè)語(yǔ)法的基礎(chǔ)上改變了一種寫(xiě)法,實(shí)現(xiàn)的功能相同,但是寫(xiě)法不同了,主要是為了讓開(kāi)發(fā)人員在使用過(guò)程中更方便易懂。

一圖勝前言(引用至 New CSS functional pseudo-class selectors :is() and :where()[1]):

支持多層層疊連用

再來(lái)看看這種情況,原本的 CSS 代碼如下:

div i

p i


div span

p span


h1 span


h1 i


如果要將上述 HTML 中,

下的的 color 設(shè)置為 red,正常的 CSS 可能是這樣:

div span,
div i,
p span,
p i {
color: red;
}

有了 :is() 后,代碼可以簡(jiǎn)化為:

:is(div, p) :is(span, i) {
color: red;
}

結(jié)果如下:

這里,也支持 :is() 的層疊連用。通過(guò) :is(div, p) :is(span, i) 的排列組合,可以組合出上述 4 行的選擇器,達(dá)到同樣的效果。

當(dāng)然,這個(gè)例子比較簡(jiǎn)單,看不出 :is() 的威力。下面這個(gè)例子就比較明顯,這么一大段 CSS 選擇器代碼:

ol ol ul,     ol ul ul,     ol menu ul,     ol dir ul,
ol ol menu, ol ul menu, ol menu menu, ol dir menu,
ol ol dir, ol ul dir, ol menu dir, ol dir dir,
ul ol ul, ul ul ul, ul menu ul, ul dir ul,
ul ol menu, ul ul menu, ul menu menu, ul dir menu,
ul ol dir, ul ul dir, ul menu dir, ul dir dir,
menu ol ul, menu ul ul, menu menu ul, menu dir ul,
menu ol menu, menu ul menu, menu menu menu, menu dir menu,
menu ol dir, menu ul dir, menu menu dir, menu dir dir,
dir ol ul, dir ul ul, dir menu ul, dir dir ul,
dir ol menu, dir ul menu, dir menu menu, dir dir menu,
dir ol dir, dir ul dir, dir menu dir, dir dir dir {
list-style-type: square;
}

可以利用 :is() 優(yōu)化為:

:is(ol, ul, menu, dir) :is(ol, ul, menu, dir) :is(ul, menu, dir) {
list-style-type: square;
}

不支持偽元素

有個(gè)特例,不能用 :is() 來(lái)選取 ::before 和 ::after 兩個(gè)偽元素。譬如:

注意,僅僅是不支持偽元素,偽類(lèi),譬如 :focus、:hover 是支持的。

div p::before,
div p::after {
content: "";
//...
}

不能寫(xiě)成:

div p:is(::before, ::after) {
content: "";
//...
}

:is 選擇器的優(yōu)先級(jí)

看這樣一種有意思的情況:


where & is test




where & is test



我們給帶有 .test-class 的元素,設(shè)置一個(gè)默認(rèn)的顏色:

div .test-class {
color: red;
}

如果,這個(gè)時(shí)候,我們引入 :is() 進(jìn)行匹配:

div :is(p) {
color: blue;
}

此時(shí),由于 div :is(p) 可以看成 div p,優(yōu)先級(jí)是沒(méi)有 div .test-class 高的,因此,被選中的文本的顏色是不會(huì)發(fā)生變化的。

但是,如果,我們?cè)?:is() 選擇器中,加上一個(gè) #test-id,情況就不一樣了。

div :is(p, #text-id) {
color: blue;
}

按照理解,如果把上述選擇器拆分,上述代碼可以拆分成:

div p {
color: blue;
}
div #text-id {
color: blue;
}

那么,我們有理由猜想,帶有 #text-id 的。

元素由于有了更高優(yōu)先級(jí)的選擇器,顏色將會(huì)變成 blue,而另外一個(gè) div p 由于優(yōu)先級(jí)不夠高的問(wèn)題,導(dǎo)致第一段文本依舊是 green。

但是,這里,神奇的是,兩段文本都變成了 blue:

CodePen Demo -- the specificity of CSS :is selector[2]。

這是由于,:is() 的優(yōu)先級(jí)是由它的選擇器列表中優(yōu)先級(jí)最高的選擇器決定的。我們不能把它們割裂開(kāi)來(lái)看。

對(duì)于 div :is(p, #text-id),is:() 內(nèi)部有一個(gè) id 選擇器,因此,被該條規(guī)則匹配中的元素,全部都會(huì)應(yīng)用 div #id 這一級(jí)別的選擇器優(yōu)先級(jí)。這里非常重要,再?gòu)?qiáng)調(diào)一下,對(duì)于 :is() 選擇器的優(yōu)先級(jí),我們不能把它們割裂開(kāi)來(lái)看,它們是一個(gè)整體,優(yōu)先級(jí)取決于選擇器列表中優(yōu)先級(jí)最高的選擇器。

:is 的別名 :matches() 與 :any()

:is() 是最新的規(guī)范命名,在之前,有過(guò)有同樣功能的選擇,分別是:

:is(div, p) span {}
// 等同于
:-webkit-any(div, p) span {}
:-moz-any(div, p) span {}
:matches(div, p) span {}

當(dāng)然,下面 3 個(gè)都已經(jīng)廢棄,不建議再繼續(xù)使用。而到今天(2022-04-27):is() 的兼容性已經(jīng)非常不錯(cuò)了,不需要兼容 IE 系列的話可以考慮開(kāi)始用起來(lái)(配合 autoprefixer),看看 CanIUse[3]:

:where 偽類(lèi)選擇器

了解了 :is 后,我們可以再來(lái)看看 :where,它們兩個(gè)有著非常強(qiáng)的關(guān)聯(lián)性。:where 同樣是將選擇器列表作為其參數(shù),并選擇可以由該列表中的選擇器之一選擇的任何元素。

還是這個(gè)例子:

:where(header, main, footer) p:hover {
color: red;
cursor: pointer;
}

上述的代碼使用了 :where,可以近似的看為:

header p:hover,
main p:hover,
footer p:hover {
color: red;
cursor: pointer;
}

這就有意思了,這不是和上面說(shuō)的 :is 一樣了么?

那么它們的區(qū)別在什么地方呢?

:is 和 :where 的區(qū)別

首先,從語(yǔ)法上,:is 和 :where 是一模一樣的。它們的核心區(qū)別點(diǎn)在于 優(yōu)先級(jí)。

來(lái)看這樣一個(gè)例子:


where & is test



CSS 代碼如下:

:is(div) p {
color: red;
}
:where(div) p {
color: green;
}

正常按我們的理解而言,:is(div) p 和 :where(div) p 都可以轉(zhuǎn)化為 div p,由于 :where(div) p 后定義,所以文字的顏色,應(yīng)該是 green 綠色,但是,實(shí)際的顏色表現(xiàn)為 color: red 紅色:

這是因?yàn)椋?where() 和 :is() 的不同之處在于,:where() 的優(yōu)先級(jí)總是為 0 ,但是 :is() 的優(yōu)先級(jí)是由它的選擇器列表中優(yōu)先級(jí)最高的選擇器決定的。

上述的例子還不是特別明顯,我們?cè)偕晕⒏脑煜拢?/p>


where & is test



我們給 div 添加上一個(gè) id 屬性,改造上述 CSS 代碼:

:is(div) p {
color: red;
}
:where(#container) p {
color: green;
}

即便如此,由于 :where(#container) 的優(yōu)先級(jí)為 0,因此文字的顏色,依舊為紅色 red。:where() 的優(yōu)先級(jí)總是為 0 這一點(diǎn)在使用的過(guò)程中需要牢記。

組合、嵌套

CSS 選擇器的一個(gè)非常大的特點(diǎn)就在于組合嵌套。:is 和 :where 也不例外,因此,它們也可以互相組合嵌套使用,下述的 CSS 選擇器都是合理的:

/* 組合*/
:is(h1,h2) :where(.test-a, .test-b) {
text-transform: uppercase;
}
/* 嵌套*/
.title:where(h1, h2, :is(.header, .footer)) {
font-weight: bold;
}

這里簡(jiǎn)單總結(jié)下,:is 和 :where 都是非常好的分組邏輯選擇器,唯一的區(qū)別在于:where() 的優(yōu)先級(jí)總是為 0,而:is() 的優(yōu)先級(jí)是由它的選擇器列表中優(yōu)先級(jí)最高的選擇器決定的。

:not 偽類(lèi)選擇器

下面我們介紹一下非常有用的 :not 偽類(lèi)選擇器。

:not 偽類(lèi)選擇器用來(lái)匹配不符合一組選擇器的元素。由于它的作用是防止特定的元素被選中,它也被稱為反選偽類(lèi)(negation pseudo-class)。

舉個(gè)例子,HTML 結(jié)構(gòu)如下:

div.a

div.b

div.c

div.d

div:not(.b) {
color: red;
}

div:not(.b) 它可以選擇除了 class 為 .b 元素之外的所有 div 元素:

MDN 的錯(cuò)誤例子?一個(gè)有意思的現(xiàn)象

有趣的是,在 MDN 介紹 :not 的頁(yè)面,有這樣一個(gè)例子:

/* Selects any element that is NOT a paragraph */
:not(p) {
color: blue;
}

意思是,:not(p) 可以選擇任何不是

標(biāo)簽的元素。然而,上面的 CSS 選擇器,在如下的 HTML 結(jié)構(gòu),實(shí)測(cè)的結(jié)果不太對(duì)勁。

p


div

span

h1


結(jié)果如下:

意思是,:not(p) 仍然可以選中

元素。我嘗試了多個(gè)瀏覽器,得到的效果都是一致的。

CodePen Demo -- :not pesudo demo[4]。

這是為什么呢?這是由于 :not(p) 同樣能夠選中 ,那么 的 color 即變成了 blue,由于 color 是一個(gè)可繼承屬性,

標(biāo)簽繼承了 的 color 屬性,導(dǎo)致看到的也是藍(lán)色。

我們把它改成一個(gè)不可繼承的屬性,試試看:

/* Selects any element that is NOT a paragraph */
:not(p) {
border: 1px solid;
}

OK,這次

沒(méi)有邊框體現(xiàn),沒(méi)有問(wèn)題!實(shí)際使用的時(shí)候,需要注意這一層繼承的問(wèn)題!

:not 的優(yōu)先級(jí)問(wèn)題

下面是一些使用 :not 需要注意的問(wèn)題。

:not、:is、:where 這幾個(gè)偽類(lèi)不像其它偽類(lèi),它不會(huì)增加選擇器的優(yōu)先級(jí)。它的優(yōu)先級(jí)即為它參數(shù)選擇器的優(yōu)先級(jí)。

并且,在 CSS Selectors Level 3[5],:not() 內(nèi)只支持單個(gè)選擇器,而從 CSS Selectors Level 4[6] 開(kāi)始,:not() 內(nèi)部支持多個(gè)選擇器,像是這樣:

/* CSS Selectors Level 3,:not 內(nèi)部如果有多個(gè)值需要分開(kāi) */
p:not(:first-of-type):not(.special) {
}
/* CSS Selectors Level 4 支持使用逗號(hào)分隔*/
p:not(:first-of-type, .special) {
}

與 :is() 類(lèi)似,:not() 選擇器本身不會(huì)影響選擇器的優(yōu)先級(jí),它的優(yōu)先級(jí)是由它的選擇器列表中優(yōu)先級(jí)最高的選擇器決定的。

:not(*) 問(wèn)題

使用 :not(*) 將匹配任何非元素的元素,因此這個(gè)規(guī)則將永遠(yuǎn)不會(huì)被應(yīng)用。

相當(dāng)于一段沒(méi)有任何意義的代碼。

:not() 不能嵌套 :not()

禁止套娃。:not 偽類(lèi)不允許嵌套,這意味著 :not(:not(...)) 是無(wú)效的。

:not() 實(shí)戰(zhàn)解析

那么,:not() 有什么特別有意思的應(yīng)用場(chǎng)景呢?我這里列舉一個(gè)。

在 W3 CSS selectors-4 規(guī)范[7] 中,新增了一個(gè)非常有意思的 :focus-visible 偽類(lèi)。

:focus-visible 這個(gè)選擇器可以有效地根據(jù)用戶的輸入方式(鼠標(biāo) vs 鍵盤(pán))展示不同形式的焦點(diǎn)。

有了這個(gè)偽類(lèi),就可以做到,當(dāng)用戶使用鼠標(biāo)操作可聚焦元素時(shí),不展示 :focus 樣式或者讓其表現(xiàn)較弱,而當(dāng)用戶使用鍵盤(pán)操作焦點(diǎn)時(shí),利用 :focus-visible,讓可獲焦元素獲得一個(gè)較強(qiáng)的表現(xiàn)樣式。

看個(gè)簡(jiǎn)單的 Demo:


button:active {
background: #eee;
}
button:focus {
outline: 2px solid red;
}

使用鼠標(biāo)點(diǎn)擊:

可以看到,使用鼠標(biāo)點(diǎn)擊的時(shí)候,觸發(fā)了元素的 :active 偽類(lèi),也觸發(fā)了 :focus偽類(lèi),不太美觀。但是如果設(shè)置了 outline: none 又會(huì)使鍵盤(pán)用戶的體驗(yàn)非常糟糕。因?yàn)楫?dāng)鍵盤(pán)用戶使用 Tab 嘗試切換焦點(diǎn)的時(shí)候,會(huì)因?yàn)?outline: none 而無(wú)所適從。

因此,可以使用 :focus-visible 偽類(lèi)改造一下:

button:active {
background: #eee;
}
button:focus {
outline: 2px solid red;
}
button:focus:not(:focus-visible) {
outline: none;
}

看看效果,分別是在鼠標(biāo)點(diǎn)擊 Button 和使用鍵盤(pán)控制焦點(diǎn)點(diǎn)擊 Button:

CodePen Demo -- :focus-visible example[8]。

可以看到,使用鼠標(biāo)點(diǎn)擊,不會(huì)觸發(fā) :foucs,只有當(dāng)鍵盤(pán)操作聚焦元素,使用 Tab 切換焦點(diǎn)時(shí),outline: 2px solid red 這段代碼才會(huì)生效。

這樣,我們就既保證了正常用戶的點(diǎn)擊體驗(yàn),也保證了無(wú)法使用鼠標(biāo)的用戶的焦點(diǎn)管理體驗(yàn),在可訪問(wèn)性方面下了功夫。

值得注意的是,這里為什么使用了 button:focus:not(:focus-visible) 這么繞的寫(xiě)法而不是直接這樣寫(xiě)呢:

button:focus {
outline: unset;
}
button:focus-visible {
outline: 2px solid red;
}

解釋一下,button:focus:not(:focus-visible) 的意思是,button 元素觸發(fā) focus 狀態(tài),并且不是通過(guò) focus-visible 觸發(fā),理解過(guò)來(lái)就是在支持 :focus-visible 的瀏覽器,通過(guò)鼠標(biāo)激活 :focus 的 button 元素,這種情況下,不需要設(shè)置 outline。

為的是兼容不支持 :focus-visible 的瀏覽器,當(dāng) :focus-visible 不兼容時(shí),還是需要有 :focus 偽類(lèi)的存在。

因此,這里借助 :not() 偽類(lèi),巧妙的實(shí)現(xiàn)了一個(gè)實(shí)用效果的方案降級(jí)。

這里有點(diǎn)繞,需要好好理解理解。

:not 兼容性

經(jīng)歷了 CSS Selectors Level 3 & CSS Selectors Level 4 兩個(gè)版本,到今天(2020-05-04),除去 IE 系列,:not 的兼容性已經(jīng)非常之好了:

:has 偽類(lèi)選擇器

OK。最后到所有邏輯選擇器里面最重磅的 :has 出場(chǎng)了。它之所以重要是因?yàn)樗恼Q生,填補(bǔ)了在之前 CSS 選擇器中,沒(méi)有核心意義上真正的父選擇器的空缺。

:has 偽類(lèi)接受一個(gè)選擇器組作為參數(shù),該參數(shù)相對(duì)于該元素的 :scope[9] 至少匹配一個(gè)元素。

實(shí)際看個(gè)例子:


div -- p




div -- p.has




div -- p



div:has(.g-test-has) {
border: 1px solid #000;
}

我們通過(guò) div:has(.g-test-has) 選擇器,意思是,選擇 div 下存在 class 為 .g-test-has 的 div 元素。

注意,這里選擇的不是 :has() 內(nèi)包裹的選擇器選中的元素,而是使用 :has() 偽類(lèi)的宿主元素。

效果如下:

可以看到,由于第二個(gè) div 下存在 class 為 .g-test-has 的元素,因此第二個(gè) div 被加上了 border。

:has() 父選擇器 -- 嵌套結(jié)構(gòu)的父元素選擇

我們?cè)偻ㄟ^(guò)幾個(gè) DEMO 加深下印象。:has() 內(nèi)還可以寫(xiě)的更為復(fù)雜一點(diǎn)。


div span




  • div ul li h2 span






div h2 span



div:has(>h2>span) {
margin-left: 24px;
border: 1px solid #000;
}

這里,要求準(zhǔn)確選擇 div 下直接子元素是 h2,且 h2 下直接子元素有 span 的 div 元素。注意,選擇的最上層使用 :has() 的父元素 div。結(jié)果如下:

這里體現(xiàn)的是嵌套結(jié)構(gòu),精確尋找對(duì)應(yīng)的父元素。

:has() 父選擇器 -- 同級(jí)結(jié)構(gòu)的兄元素選擇

還有一種情況,在之前也比較難處理,同級(jí)結(jié)構(gòu)的兄元素選擇。

看這個(gè) DEMO:

div + p

p


div + h1

h1


div + h2

h2


div + ul

    ul

我們想找到兄弟層級(jí)關(guān)系中,后面接了

元素的  ??.has-test?? 元素,可以這樣寫(xiě):

.has-test:has(+ h2) {
margin-left: 24px;
border: 1px solid #000;
}

效果如下:

這里體現(xiàn)的是兄弟結(jié)構(gòu),精確尋找對(duì)應(yīng)的前置兄元素。

這樣,一直以來(lái),CSS 沒(méi)有實(shí)現(xiàn)的父選擇器,借由 :has() 開(kāi)始,也能夠做到了。這個(gè)選擇器,能夠極大程度的提升開(kāi)發(fā)體驗(yàn),解決之前需要比較多 JavaScript 代碼才能夠完成的事。

上述 DEMO 匯總,你可以戳這里 CodePen Demo -- :has Demo[10]。

:has() 兼容性,給時(shí)間一點(diǎn)時(shí)間

比較可惜的是,:has() 在最近的 Selectors Level 4[11] 規(guī)范中被確定,目前的兼容性還比較慘淡,截止至 2022-05-04,Safari 和 最新版的 Chrome(V101,可通過(guò)開(kāi)啟 Experimental Web Platform features 體驗(yàn))。

Chrome 下開(kāi)啟該特性需要,1. 瀏覽器 URL 框輸入 chrome://flags,2. 開(kāi)啟 #enable-experimental-web-platform-features。

耐心等待,給給時(shí)間一點(diǎn)時(shí)間,這么好的選擇器馬上就能大規(guī)模應(yīng)用了。

最后

本文到此結(jié)束,希望對(duì)你有幫助 ????

參考資料

  • [1]New CSS functional pseudo-class selectors :is() and :where(): https://web.dev/css-is-and-where/。
  • [2]CodePen Demo -- the specificity of CSS :is selector: https://codepen.io/Chokcoco/pen/rNJaGvb。
  • [3]CanIUse: https://caniuse.com/?search=%3Amatches。
  • [4]CodePen Demo -- :not pesudo demo: https://codepen.io/Chokcoco/pen/KKZbWjy。
  • [5]CSS Selectors Level 3: https://www.w3.org/TR/selectors-3/。
  • [6]CSS Selectors Level 4: https://www.w3.org/TR/selectors-4/。
  • [7]W3 CSS selectors-4 規(guī)范: https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo。
  • [8]CodePen Demo -- :focus-visible example: https://codepen.io/Chokcoco/pen/abBbPrE。
  • [9]:scope: https://developer.mozilla.org/zh-CN/docs/Web/CSS/:scope。
  • [10]CodePen Demo -- :has Demo: https://codepen.io/Chokcoco/pen/poaJjwm。
  • [11]Selectors Level 4: https://drafts.csswg.org/selectors/#relational。
  • [12]Github -- iCSS: https://github.com/chokcoco/iCSS。


文章名稱:淺談邏輯選擇器Is、Where、Not、Has
鏈接地址:http://www.5511xx.com/article/djeshpd.html