搜尋

CSS @scope 作用域

開發網頁時,隨著架構複雜度的增加,管理 CSS 樣式也變得更加困難。為了避免樣式互相污染和提升維護性,CSS 加入了 @scope 規則定義,透過「作用域」的概念,讓開發者能更精確的控制樣式範圍,這篇教學會介紹 @scope 的概念、用法、嵌套、權重以及 :scope 虛擬類別選擇器的相互應用。

快速導覽:

CSS 教學 - CSS @scope 作用域

教學影片

搭配教學影片一起閱讀,效果會更好!歡迎大家訂閱 STEAM 教育學習網的 Youtube 頻道

前往:https://www.youtube.com/@steam.oxxostudio

認識 CSS @scope

@scope 是 CSS 裡的一種 At 規則,可以將樣式限制在某個 DOM 結構中 ( 或某個選擇器的範圍 ),通常 @scope 會用來解決樣式外漏 ( style leakage ) 或改善選擇器權重衝突,由於 @scope 提升讓 CSS 進階為模組化的架構,十分適合在元件導向的網頁開發,例如 Web Components 或大型 UI 區塊模組。

基本語法如下,使用小括號「()定義選擇器:

@scope (選擇器) {
  樣式規則...
}

下方範例會透過 @scope,讓只有 class 為 a 裡的 h2 變成紅色,其他的 h2 保持黑色。

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

<!-- HTML 程式碼 -->
<h2>apple</h2>
<div class="a">
  <h2>oxxo</h2>
</div
<div class="b">
  <h2>banana</h2>
</div>

<!-- CSS 程式碼 -->
<style>
  @scope (.a) {
    h2 {
      color: red;
    }
  }
</style>

CSS 教學 - CSS @scope 作用域 - CSS @scope 基本寫法

@scope 限制範圍

除了基本的用法,@scope 也可以透過「to」去限制作用域的範圍,表示「範圍要延伸到的選擇器,但不包含該選擇器」,寫法如下:

@scope (起點選擇器) to (終點選擇器) {
  /* 限定範圍內的樣式 */
}

下方範例會透過 @scope 搭配 to,讓只有 a 裡的 h2 變成紅色,但在 a 裡頭的 b 裡的 h2 仍然保持黑色,範例同時列出使用「虛擬類別 :not」選擇器的寫法,可以看出 @scope 的架構更容易理解且也更清晰。

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

<!-- HTML 程式碼 -->
使用 @scope
<div class="a">
  <h2>我會變色</h2>
  <div class="b">
    <h2>我不會變色</h2>
  </div>
</div>

使用虛擬類別 :not
<div class="c">
  <h2>我會變色</h2>
  <div class="d">
    <h2>我不會變色</h2>
  </div>
</div>

<!-- CSS 程式碼 -->
<style>
  .a, .c {
    border: 1px solid #000;
    margin: 5px 0 20px;
  }
  @scope (.a) to (.b) {
    h2 {
      color: red;
    }
  }
  .c > h2, .c *:not(.d) h2 {
    color: red;
  }
</style>

CSS 教學 - CSS @scope 作用域 - CSS @scope 限制範圍

除了「虛擬元素」和「標籤選擇器」,@scope 支援其他所有選擇器語法,也可以使用「逗號」加入多組選擇器,下方範例會透過多組選擇器,限制在不同狀況下顏色會變成原本為預設的黑色 ( 在 b 裡、hover 時、有 title 屬性時 )。

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

<!-- HTML 程式碼 -->
<div class="a">
  <h2>我會變色</h2>
  <div class="b">
    <h2>( .b 裡 ) 我不會變色</h2>
  </div>
  <h2>我會變色</h2>
  <h2 title="test">( 有 title ) 我不會變色</h2>
</div>

<!-- CSS 程式碼 -->
<style>
  @scope (.a) to (.b, [title], h2:hover) {
    h2 {
      color: red;
    }
  }
</style>

CSS 教學 - CSS @scope 作用域 - CSS @scope 使用多組選擇器限制範圍

@scope 的權重

使用 @scope 時也需要遵守 CSS「權重」原則,但如果「作用域裡的選擇器權重和作用域外的權重相同」時,會優先使用作用域裡的選擇器,下方範例會展示權重的差異,當權重不同時,仍然以權重大的為主,當權重相同時,以 @scope 的樣式為主。

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

<!-- HTML 程式碼 -->
<div class="a">
  <h2>我是 scope 定義紅色</h2>
  <h3>我是外部定義綠色</h3>
</div>

<!-- CSS 程式碼 -->
<style>
  /* 雖然放前面,但權重比較大,還是蓋過後面的 */
  .a h3 {
    color: green; /* 權重 0-1-1 */
  }
  @scope (.a) {
    h2, h3 {
      color: red; /* 權重 0-0-1 */
    }
  }
  /* 雖然權重相同又放後面,但該選擇器位於 @scope 中,以 @scope 為主 */
  h2 {
    color: green; /* 權重 0-0-1 */
  }
</style>

CSS 教學 - CSS @scope 作用域 - CSS @scope 的權重

:scope 虛擬類別選擇器與「&」特殊符號

使用 @scope 時,可以額外使用 :scope 虛擬類別選擇器和 & 特殊符號,兩者說明如下:

  • :scope:表示該作用域的「根元素」,類似整份 HTML 的 :root
  • &:表示巢狀結構中的「自己」,也就是 @scope 的選擇器本身。

下方範例會使用 :scope 定義 CSS 變數,該變數只會作用於 @scope 的範圍中。

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

<!-- HTML 程式碼 -->
<div class="a">
  <h2>我 :scope 裡定義的顏色字體</h2>
</div>
<h2>我讀取不到變數,使用預設顏色字體</h2>

<!-- CSS 程式碼 -->
<style>
  @scope (.a) {
    :scope {
      --c: red;
      --size: 30px;
    }
    h2 {
      color: var(--c);
      font-size: var(--size);
    }
  }
  h2 {
    color: var(--c);         /* 讀取不到,使用預設顏色 */
    font-size: var(--size);  /* 讀取不到,使用預設大小 */
  }
</style>

CSS 教學 - CSS @scope 作用域 - CSS @scope 的 :scope 虛擬類別選擇器

下方範例會使用 & 代表自身選擇器,透過這種方式可以增加權重,因為加上了自身選擇器的權重,當權重相同時就會優先使用 @scope 裡的樣式。

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

<!-- HTML 程式碼 -->
<div class="a">
  <h2>我有使用 & 增加權重,所以是紅色</h2>
  <h3>我只是基本的 @scope</h3>
</div>

<!-- CSS 程式碼 -->
<style>
  @scope (.a) {
    & h2 {
      color: red; /* 權重 0-1-1,權重相同時優先使用 @scope 裡的樣式 */
    }
    h3 {
      color: red; /* 權重 0-0-1 */
    }
  }
  .a h2, .a h3 {
    color: green; /* 權重 0-1-1 */
  }
</style>

CSS 教學 - CSS @scope 作用域 - CSS @scope 使用 & 特殊符號

@scope 嵌套的巢狀結構

雖然 @scope 已經是一個類似嵌套的巢狀結構,但裡面又放入另一個 @scope 之後,就更能實現層層套疊、各自隔離的樣式控制,讓同一份樣式在不同模組中可以擁有不同表現,不必額外增加許多選擇器進行權重控制管理,通常這種做法較適合大型 CSS 架構,在一般的使用情境較為少見。

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

<!-- HTML 程式碼 -->
<div class="a">
  <div class="a1">
    <h2>我在 .a1 裡面,是綠色</h2>
  </div>
  <div class="a2">
    <h2>我在 .a2 裡面,是紅色</h2>
  </div>
</div>

<!-- CSS 程式碼 -->
<style>
  @scope (.a) {
    h2 {
      color: red;
    }
    @scope (.a1) {
      h2 {
        color: green;
      }
    }
  }
</style>

CSS 教學 - CSS @scope 作用域 - CSS @scope 嵌套的巢狀結構

@scope 和純粹使用選擇器的差異

當元素巢狀結構越複雜,要透過單純的邏輯與文件結構選擇器控制樣式,就會產生許多權重互相干擾的狀況,但 @scope因為可以將選擇器限縮在指定的範圍,就可以在指定架構中輕鬆地調整樣式,下方範例會透過 @scope:not 虛擬類別選擇器,分別控制 HTML 巢狀結構的元素樣式,可以看出兩者顯著的差異。

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

<!-- HTML 程式碼 -->
使用 @scope
<div class="a">
  <h2>我是紅色</h2>
  <div>
    <h2>我是紅色</h2>
  </div>
  <div class="aa">
    <div class="aaa">
      <h2>我是黑色</h2>
    </div>
    <h2>我是綠色</h2>
  </div>
</div>
  
使用 :not
<div class="b">
  <h2>我是紅色</h2>
  <div>
    <h2>我是紅色</h2>
  </div>
  <div class="bb">
    <div class="bbb">
      <h2>我是黑色</h2>
    </div>
    <h2>我是綠色</h2>
  </div>
</div>

<!-- CSS 程式碼 -->
<style>
  .a, .b {
    width: 200px;
    border: 1px solid #000;
    margin: 5px 0 20px;
  }
  h2 {margin: 5px;}

  /* 使用 @scope */
  @scope (.a) to (.aaa) {
    h2 {color: red;}        /* .a~.aaa 中的 h2 */
    .aa h2 {color: green;}  /* .a~.aaa 中的 .aa h2 */
  }

  /* 使用 :not 和文件結構 */             
  /* .b 第一層的 h2 和 .b 裡不包含 .bbb div 的第一層 h2 */
  .b > h2,
  .b div:not(.bbb)>h2{
    color: red;
  }
  /* .b 的 .bb div 的第一層 h2 */
  .b div.bb > h2 {
    color: green;
  }
</style>

CSS 教學 - CSS @scope 作用域 - CSS @scope 和純粹使用選擇器的差異

小結

@scope 是一個讓 CSS 更具模組化的重要功能,不僅能限制樣式作用範圍,也改善了樣式覆蓋與衝突問題,隨著瀏覽器支援度提升,只要好好善用 @scope,就可以撰寫出穩定又好維護的 CSS 喔。

意見回饋

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

CSS 教學

基本介紹

認識 CSS 開始使用 CSS CSS 語法規則 CSS 命名原則 CSS 常用樣式屬性

CSS 選擇器

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

數值與單位

全域關鍵字與文字數值 長度與角度單位 位置名稱與時間單位 特殊樣式屬性 ( all、appearance)

規則與定義

變數 ( Variables ) 媒體查詢 ( @media ) 容器查詢 ( @container ) 自訂屬性值 ( @property ) 匯入樣式 ( @import ) 分層優先順序 ( @layer ) 選擇器作用域 ( @scope ) 定義字型 ( @font-face ) 計數規則 ( @counter-style ) 列印網頁 ( @page )

函式類型

數學計算 文字與清單計數 形狀與線段 路徑 ( path )

顏色與濾鏡

顏色單位 色彩模型 相對顏色 漸層色 影像濾鏡 ( filter ) 背景濾鏡 ( backdrop-filter ) 混合模式 ( mix-blend-mode )

文字與段落

設定字型 ( font-family ) 使用外部字型 文字尺寸 文字樣式 ( 常用 ) 文字樣式 ( 其他實用 ) 文字樣式 ( 特殊用途 ) 文字換行 文字空白與 Tab 大小 文字行高與縮排 文字水平與垂直對齊 文字書寫方向 文字自動分欄 使用 Color Font ( 彩色字型 ) 使用 Icon Font ( 圖示文字 ) 製作自己的 Icon Font 顯示生成內容與引號

元素容器

容器顯示類型 ( display ) 元素 display 對照表 盒子模型 ( Box Model ) 寬高尺寸 內邊距 ( padding ) 外邊界 ( margin ) 邊框 ( border ) 邊框圓角 ( border-radius ) 影像邊框 ( border-image ) 輪廓 ( outline ) 內容溢出與裁切 ( overflow ) 內容範圍 ( contain ) 可見性與透明度 縮放與調整 ( zoom、resize )

背景與陰影

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

清單與表格

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

基本排版與定位

元素排版方式 浮動 ( float ) 浮動形狀 ( shape-* ) 定位 ( position ) 邏輯屬性 ( logical properties ) 重置 CSS ( Reset CSS ) 水平置中技巧 垂直置中技巧

Flex 彈性排版

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

Grid 網格排版

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

轉場與動畫

轉場 ( transition ) 轉場觸發事件 動畫 ( animation ) 自訂動畫路徑 ( offset ) 動畫觸發事件 多重動畫的權重與順序 動畫進度控制 ( timeline )

變形、裁切與遮罩

裁切路徑 ( clip-path ) 影像遮罩 ( mask ) 物件填滿方式與定位 轉換函式 ( transform ) 平移、旋轉與縮放 3D 轉換與透視

視窗與使用者行為

捲軸樣式 ( scrollbar ) 拉霸、滑桿樣式 ( slider ) 滑鼠游標圖示 ( cursor ) 滑鼠事件 ( pointer-events ) 使用者選取 ( user-select ) 捲動行為 ( scroll、overscroll ) 列印換頁 ( break-* )

CSS 預處理器

認識 CSS 預處理器 Less ( 安裝、開始使用 ) Less ( 巢狀結構、選擇器 ) Less ( 變數、import ) Less ( Extend、Mixin ) Less ( 邏輯、迴圈、函式 )

範例效果

CSS 圓餅圖 CSS 跑馬燈 Google 載入動畫 電子時鐘數字 漸層色的轉場與動畫 漸層色製作星空背景 漸層色邊框 漸層色製作圖案背景 不規則形狀動畫 彈跳的正方形動畫 3D 正多面體 超連結底線動畫效果 噁心黏黏球效果 CSS 視差滾動效果 捲軸控制放射形選單 捲軸改變文字背景色 CSS 頁面捲動進度條 CSS 水波效果 圓點載入動畫 ( 陰影動畫 ) 字母翻牌效果 探照燈動畫 立體雙色跑馬燈 樓梯文字動態效果 漸層色文字、雙色文字 流動色彩文字 空心文字、文字水波背景 左右傾斜的背景效果 Icon 圖示形狀變換 故障文字效果 按鈕的多種 hover 效果 點擊展開或收折的選單 點擊愛心圖案放射效果 純 CSS 數字載入進度條 純 CSS 碼表 ( 可計時 )