搜尋

虛擬類別選擇器 ( 邏輯判斷 )

這篇教學會介紹「邏輯判斷」虛擬類別選擇器,這個選擇器主要有 :not()、:is() 和 :has() 三種,透過邏輯判斷的規則,就能從複雜的結構中挑選出符合規律的元素,是一種非常強大的 CSS 選擇器。

CSS 教學 - 虛擬類別選擇器 ( 邏輯判斷 )

「邏輯判斷」虛擬類別選擇器

下方列出和「邏輯判斷」有關的虛擬類別選擇器 ( 支援度 All 表示主流瀏覽器都支援 ):

虛擬類別選擇器 說明 支援度
:not() 否定選擇器。 All
:is():where() 任意比對選擇器。 IE 不支援
:has() 結構關係選擇器。 IE 不支援

:not()

:not()」表示「否定選擇器」,撰寫方式為「:not(選擇器)」,意思是「不是這個選擇器」的元素,下方的範例執行後,不是 h3 裡的元素就會是紅色 ( 注意因為 color 有繼承特性,所以 :not() 前方要加上 body )。

線上展示:https://codepen.io/oxxo/pen/PovNrQd

<!-- HTML 程式碼 -->
<h2>oxxo</h2>
<h3>apple</h3>
<h4>banana</h4>
<h5>orange</h5>

<!-- CSS 程式碼 -->
<style>
  body :not(h3) {color: red;} 
</style>

CSS 教學 - 虛擬類別選擇器 ( 邏輯判斷 ) - :not()

通常實際使用時,會將 :not() 前方串接指定選擇器,使其更有邏輯的「意義」,也能更進一步將範圍縮小在指定選擇器裡,下方的範例執行後,所有的 class 不是 apple 的 li 元素,就會變成紅色文字。

線上展示:https://codepen.io/oxxo/pen/abrNgKp

<!-- HTML 程式碼 -->
<ul>
  <li>oxxo</li>
  <li class="apple">apple</li>
  <li>banana</li>
  <li>orange</li>
</ul>

<!-- CSS 程式碼 -->
<style>
  li:not(.apple) {color: red;} 
</style>

CSS 教學 - 虛擬類別選擇器 ( 邏輯判斷 ) - :not()

:not() 支援較為複雜選擇器規則,只要是「正確的選擇器」,都可以被 :not 比對並且排除,下方列出一些不同的選擇器規則,分別對應排除後所呈現的樣式:

線上展示:https://codepen.io/oxxo/pen/YzbqmWJ

<!-- HTML 程式碼 -->
<ul class="g1">
  <li>oxxo</li>
  <li class="fruit" name="apple">apple</li>
  <li class="fruit" name="banana">banana</li>
  <li class="fruit">orange</li>
</ul>
<ul class="g2">
  <li>oxxo</li>
  <li class="fruit" name="apple">apple</li>
  <li class="fruit" name="banana">banana</li>
  <li class="fruit">orange</li>
</ul>
<ul class="g3">
  <li>oxxo</li>
  <li class="fruit" name="apple">apple</li>
  <li class="fruit" name="banana">banana</li>
  <li class="fruit">orange</li>
</ul>
<ul class="g4">
  <li>oxxo</li>
  <li class="fruit" name="apple">apple</li>
  <li class="fruit" name="banana">banana</li>
  <li class="fruit">orange</li>
</ul>

<!-- CSS 程式碼 -->
<style>
  ul {border: 1px solid black;}                  /* ul 外框 */
  .g1 li:not(.fruit) {background: orange;}       /* 排除 class 為 fruit 的 li */
  .g2 li:not(.fruit[name]) {background: pink;}   /* 排除 class 為 fruit 且具有 name 屬性的 li */
  .g3 li:not(.fruit:nth-child(2)) {background: green;}  /* 排除 class 為 fruit 且位在第二個子元素的 li */
  .g4 li:not(.fruit, [name]) {background: cyan;} /* 排除 class 為 fruit 或具有 name 屬性的 li */
</style>

CSS 教學 - 虛擬類別選擇器 ( 邏輯判斷 ) - :not()

:not 也支援「雙重否定」的寫法 ( :not(:not()) ),但這種寫法比較不容易理解,且容易與「:not():not()」發生混淆,因此不建議使用

舉例來說,「:not([name]:not(.apple))」表示「選取不要有 name 屬性且不要 class 不要是 fruit 的 li 元素」( 不知道在說什麼 ),但「:not(li):not(.apple)」卻是「不要屬性 name 也不要 class 為 fruit 的 li 元素」。

線上展示:https://codepen.io/oxxo/pen/PovNMOY

<!-- HTML 程式碼 -->
<ul class="g1">
  <li>oxxo</li>
  <li class="fruit" name="apple">apple</li>
  <li class="fruit" name="banana">banana</li>
  <li class="fruit">orange</li>
</ul>
<ul class="g2">
  <li>oxxo</li>
  <li class="fruit" name="apple">apple</li>
  <li class="fruit" name="banana">banana</li>
  <li class="fruit">orange</li>
</ul>

<!-- CSS 程式碼 -->
<style>
  ul {border: 1px solid black;}
  .g1 li:not([name]:not(.fruit)) {background: pink;}
  .g2 li:not([name]):not(.fruit) {background: orange;}
</style>

CSS 教學 - 虛擬類別選擇器 ( 邏輯判斷 ) - :not()

:is()、:where()

:is()」和「:where()」表示「任意比對選擇器」,意思為「指定的元素」,由於這兩個虛擬類別選擇器也支援較複雜的選擇器語法,因此常用在「簡化 CSS 程式碼」,舉例來說,如果有好幾個父元素都對應到同樣名稱的子元素,就能利用 :is():where() 簡化。

線上展示:https://codepen.io/oxxo/pen/OJYNKEP

<!-- HTML 程式碼 -->
<ul class="g1">
  <li><span>oxxo</span></li>
  <li class="fruit1" name="apple"><span>apple</span></li>
  <li class="fruit2" name="banana"><span>banana</span></li>
  <li class="fruit3"><span>orange</span></li>
</ul>
<ul class="g2">
  <li><span>oxxo</li>
  <li class="fruit1" name="apple"><span>apple</span></li>
  <li class="fruit2" name="banana"><span>banana</span></li>
  <li class="fruit3"><span>orange</span></li>
</ul>

<!-- CSS 程式碼 -->
<style>
  ul {border: 1px solid black;}
  .g1 li.fruit1 span,
  .g1 li.fruit2 span,
  .g1 li.fruit3 span{
    background: pink;    /* 原本的寫法 */
  }
  .g2 li:is(.fruit1, .fruit2, .fruit3) span{
    background: orange;  /* 改用 :is(),使用 :where() 也是相同結果 */
  }
</style>

CSS 教學 - 虛擬類別選擇器 ( 邏輯判斷 ) - :is()、:where()

雖然 :is():where() 很像,但兩者差異在於「權重」,使用 :is() 後的權重等於所比對選擇器的權重,而 :where()權重是 0,下方的範例執行後可以看到上半部使用 :is(),所以權重是 0-2-2 ( 兩個 class 和兩個元素 ),所以會顯示樣式,但使用 :where() 不會有任何權重加成,只會使用原本的 0-1-2,因此如果在排列順序後方有相同權重的選擇器,樣式就會被覆蓋。

線上展示:https://codepen.io/oxxo/pen/mdYPNQb

<!-- HTML 程式碼 -->
<ul class="g1">
  <li><span>oxxo</span></li>
  <li class="fruit1" name="apple"><span>apple</span></li>
  <li class="fruit2" name="banana"><span>banana</span></li>
  <li class="fruit3"><span>orange</span></li>
</ul>
<ul class="g2">
  <li><span>oxxo</li>
  <li class="fruit1" name="apple"><span>apple</span></li>
  <li class="fruit2" name="banana"><span>banana</span></li>
  <li class="fruit3"><span>orange</span></li>
</ul>

<!-- CSS 程式碼 -->
<style>
  ul {border: 1px solid black;}

  .g1 li:is(.fruit1, .fruit2, .fruit3) span{
    background: orange;   /* 權重 0-2-2 */
  }
  .g1 li span{
    background: green;   /* 權重 0-1-2 */
  }

  .g2 li:where(.fruit1, .fruit2, .fruit3) span{
    background: orange;  /* 權重 0-1-2 */
  }
  .g2 li span{
    background: green;  /* 權重 0-1-2,因為擺在後面,所以會套用這個樣式 */
  }
</style>

CSS 教學 - 虛擬類別選擇器 ( 邏輯判斷 ) - :is()、:where() 權重差異

:has()

:has()」表示「結構關係選擇器」,意思為「有沒有特定的子元素」,這是主流瀏覽器近期才支援的強大選擇器,也是唯一類似「子元素選取父元素」的選擇器,以下方的範例而言,如果 li 裡有 span 這個子元素,這個 li 就會加上底色。

線上展示:https://codepen.io/oxxo/pen/PovNMMZ

<!-- HTML 程式碼 -->
<ul class="g1">
  <li>oxxo</li>
  <li class="fruit1" name="apple"><span>apple</span></li>
  <li class="fruit2" name="banana"><span>banana</span></li>
  <li class="fruit3"><span>orange</span></li>
</ul>
<nav>
  <h2>oxxo</h2>
  <h3><span>hello world!!</span></h3>
  <ul>
    <li>grape</li>
    <li>papaya</li>
    <li><span>coconut</span></li>
  </ul>
</nav>

<!-- CSS 程式碼 -->
<style>
  li:has(span) {background: pink;}  /* 如果 li 裡有 span */
</style>

CSS 教學 - 虛擬類別選擇器 ( 邏輯判斷 ) - :has()

小結

「邏輯判斷」的虛擬類別選擇器非常的強大好用!特別是近期各家瀏覽器都支援複雜選取器的判斷後,更是能利用「邏輯判斷」的方式大幅改善原本的 CSS 結構,非常推薦立刻開始使用喔!

意見回饋

如果有任何建議或問題,可傳送「意見表單」給我,謝謝~

CSS 教學

基本介紹

認識 CSS 開始使用 CSS CSS 語法規則 CSS 命名原則

CSS 選擇器

認識 CSS 選擇器 優先順序 ( 權重 ) 樣式繼承與聯集 元素選擇器 ID 和 Class 選擇器 屬性選擇器 文件結構選擇器 虛擬類別選擇器 ( 結構 ) 虛擬類別選擇器 ( 類型 ) 虛擬類別選擇器 ( 輸入 ) 虛擬類別選擇器 ( 行為 ) 虛擬類別選擇器 ( 超連結 ) 虛擬類別選擇器 ( 邏輯 ) 虛擬類別選擇器 ( 其他 ) 虛擬元素選擇器 群組與組合選擇器

數值與單位

關鍵字與文字數值 長度與角度單位 顏色單位 位置名稱與時間單位

變數與內容函式

變數 數學計算 文字與清單計數 生成內容與引號

顏色與濾鏡

色彩模型 漸層色 影像濾鏡

文字樣式

使用通用字型 使用外部字型 @font-face 定義字型 文字尺寸 常用文字樣式 文字換行 文字空白與 Tab 大小 文字行高與縮排 文字水平與垂直對齊 文字書寫方向 特殊文字樣式

元素容器

容器顯示類型 ( display ) 元素 display 對照表 盒子模型 ( Box Model ) 寬度與高度 內邊距 ( padding ) 外邊界 ( margin ) 邊框 ( border ) 邊框圓角 影像邊框 輪廓 ( outline ) 可見性與透明度 內容溢出與裁切

背景與陰影

背景顏色 背景圖 ( 定位、尺寸 ) 背景圖 ( 固定、重複 ) 背景圖 ( 多重背景、混合 ) 背景縮寫 ( background ) 容器陰影 ( box-shadow )

清單與表格

清單樣式 清單計數器 定義計數規則 表格基本樣式 表格邊框樣式 表格內容寬度與對齊

基本排版與定位

元素排版方式 浮動 ( float ) 浮動形狀 定位 ( position )

Flexbox 彈性排版

Flexbox 彈性盒子 Flexbox 對齊方式 Flexbox 彈性伸縮

Grid 網格排版

Grid 網格容器與格線 Grid 網格空間與命名 Grid 網格流向與間距 Grid 排列網格項目 Grid 項目對齊與順序

轉場與動畫

轉場 ( transition ) 轉場觸發事件 動畫 ( animation ) 動畫觸發事件 多重動畫的權重與順序

變形、裁切與遮罩

裁切路徑 ( clip-path ) 影像遮罩 ( mask )