CSSCSS Selectorhtml:root:scopeCSS Tips2026

你不知道的 CSS 技巧:選擇 <html> 的 6 種方法

整理 CSS 中選擇 <html> 元素的各種方法:html、:root、:scope、:has()、:not(),以及一隻隱藏的小鳥彩蛋 🐦。

· 4 分鐘閱讀

大多數前端工程師寫 CSS 的第一天就學會了 html { ... } 這個選擇器。但你知道嗎,CSS 裡有至少六種方式可以選擇 <html> 元素?有些是日常實用的,有些純粹是趣味知識——比如 :not(* > *) 會給你一隻小鳥 🐦。這篇文章不是要顛覆你對 CSS 的理解,而是讓你在同事面前小小的炫一下。


為什麼要討論這個

在多數情況下,html { ... }body { ... } 就足夠了。但這些替代方法的價值在於:

  1. 拓寬你對 CSS 選擇器的理解
  2. 應對特殊場景(如 SVG 文件、Shadow DOM)
  3. 純粹的樂趣——CSS 可以很有趣

方法一:直接使用標籤名

/* 最基本的方式 */
html {
  scroll-behavior: smooth;
  font-family: system-ui, sans-serif;
}

這是所有人都知道的方法,沒有什麼驚喜。


方法二::root——最實用的替代方案

/* :root 匹配文檔根元素 */
:root {
  /* 在 HTML 文件中,:root 等於 <html> */
  --color-primary: #4f46e5;
  --spacing-unit: 8px;
  --font-family: 'Inter', system-ui, sans-serif;
}

:root 的優勢

維度html:root
優先級0-0-1(元素選擇器)0-1-0(偽類)
支援 XML❌ 僅 HTML✅ 支援 SVG、RSS、MathML
宣告 CSS 變數✅(更常見)

:root 的優先級更高,這在某些覆蓋場景裡很有用。

實際應用

/* :root 是宣告全域 CSS 變數的最佳位置 */
:root {
  /* 設計 Token */
  --color-brand: #4f46e5;
  --color-brand-light: #818cf8;
  --color-brand-dark: #3730a3;

  /* Spacing */
  --space-1: 4px;
  --space-2: 8px;
  --space-4: 16px;
  --space-8: 32px;

  /* Typography */
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;

  /* Animation */
  --transition-fast: 150ms ease;
  --transition-normal: 300ms ease;
}

/* 在其他地方使用 */
.button {
  background: var(--color-brand);
  padding: var(--space-2) var(--space-4);
  transition: var(--transition-fast);
}

XML 支援

:root 不只是為 HTML 設計的——它適用於所有 XML 文檔:

<!-- SVG 文件 -->
<svg xmlns="http://www.w3.org/2000/svg">
  <style>
    :root {
      fill: #4f46e5;
    }
  </style>
  <rect width="100" height="100"/>
</svg>
<!-- RSS/Atom feed -->
<rss version="2.0">
  <style>
    :root {
      font-family: Arial, sans-serif;
    }
  </style>
  <channel>
    <!-- ... -->
  </channel>
</rss>

方法三::scope——明確的作用域根

/* :scope 匹配當前作用域的根元素 */
:scope {
  /* 在全域作用域中,:scope 等於 <html> */
  font-size: 16px;
}

:scope 的設計目的是明確標記作用域的根元素,在 CSS @scope 規則中特別有用:

/* @scope 區塊內的作用域根 */
@scope (.card) {
  :scope .card-header {
    /* :scope 在這裡指的是 .card */
    font-weight: bold;
  }
}

在全域作用域中,:scope:root 都能匹配 <html>,但語義不同:

  • :root:文檔根元素
  • :scope:當前作用域的根元素

方法四:&——在嵌套中引用根

Sass/SCSS 或現代 CSS 嵌套語法中的 &

/* 在非嵌套上下文中的 & */
/* 現代 CSS(Chrome 120+)*/
& {
  font-size: 16px;
}

/* 在 Sass/SCSS */
& {
  font-size: 16px;
}

&最外層(非嵌套)時,它等於 <html>

嵌套中的 &

/* 嵌套中的 & */
.page {
  & .header {
    /* & 在這裡指的是 .page */
    background: white;
  }

  & {
    /* 這個 & 等於 .page */
    color: #333;
  }
}

:scope 的關係

& 在嵌套的根位置,與 :scope 有相似的語義——都指向某個作用域的根。


方法五::has(head):has(body)——利用 Has 偽類

/* :has() 選擇包含特定子元素的父元素 */
/* <html> 是唯一同時包含 <head> 和 <body> 的元素 */
html:has(head) {
  /* 匹配有 <head> 的 <html> */
}

html:has(body) {
  /* 匹配有 <body> 的 <html> */
}

/* 兩個都寫等於匹配 <html> */
html:has(head):has(body) {
  /* 這個選擇器幾乎就是 <html> 本身 */
}

實際用途

老實說,這個方法沒有實際用途——<html> 永遠都有 <head><body>。但它展示了 :has() 偽類的強大之處。

/* 一個更實際的 :has() 用法 */
.card:has(.badge) {
  /* 匹配包含 badge 元素的卡片 */
  position: relative;
}

.card:has(.badge)::after {
  content: '';
  position: absolute;
  top: -4px;
  right: -4px;
  width: 12px;
  height: 12px;
  background: red;
  border-radius: 50%;
}

方法六::not(* *)——利用否定偽類

/* :not(* *) = 不被任何元素包含的元素 */
/* 只有 <html> 符合這個條件 */
:not(* *) {
  background: #f9fafb;
}

/* :not(* > *) = 不是任何元素的直接子元素 */
:not(* > *) {
  /* 這個選擇器本身沒有實際效果 */
  /* 但在某些瀏覽器中可能匹配到 <html> */
}

小鳥彩蛋 🐦

CSS-Tricks 的文章提到了一個有趣的彩蛋。試試這個:

:not(* > *)::before {
  content: '🐦';
}

在一些瀏覽器環境下,這可能會在 <html> 元素前面顯示一隻小鳥。


方法七:* + 祖先選擇(bonus)

/* 這個方法的極致變體 */
/* <html> 是唯一沒有祖先的元素 */
*:not(:has(:not(:has(:not(*))))) {
  /* 這是一個過度複雜的選擇器 */
  /* 基本上等同於選擇 <html> */
}

這個例子只是為了說明——CSS 選擇器的組合可以是無限的,但不代表你應該這樣寫。


優先級比較

選擇器優先級實用性
html0-0-1⭐⭐⭐⭐⭐
:root0-1-0⭐⭐⭐⭐⭐
:scope0-1-0⭐⭐⭐
&(在最外層)取決於上下文⭐⭐
:has(head)0-1-1(需驗證)
:not(* *)0-1-1(需驗證)

推薦:什麼情況下用哪個

宣告全域 CSS 變數

/* 推薦:使用 :root */
:root {
  --color-primary: #4f46e5;
}

設定基礎字體大小

/* 推薦:使用 html */
html {
  font-size: 16px;
  scroll-behavior: smooth;
}

在 @scope 中使用

/* 使用 :scope */
@scope (.card) {
  :scope {
    /* scope 根元素 */
  }
}

結語:CSS 選擇器的藝術

這六種方法,涵蓋了從「每個人都知道」到「純粹是彩蛋」的範圍。實用的建議很簡單:

  • 宣告 CSS 變數:用 :root
  • 設定基礎樣式:用 html:root
  • 在 @scope 中:用 :scope

其他的方法——:has():not()、嵌套中的 &——更多是展示 CSS 選擇器的靈活性和深度。了解它們可以拓寬你對 CSS 的理解,有時候也能在特殊場景派上用場。

至于那只小鳥 🐦——就當作是 CSS 給你的一個小驚喜吧。


本文是「2026 CSS 實用技術」系列文章之一。