網站導覽

撰寫樣式

路由層級樣式

以共用定義支援區域傳遞的路由 CSS,並區分參照脈絡、原生規則與選擇器作用範圍。

本頁目錄

#概覽

頁面版面與一次性樣式應放在該頁面旁,由所屬路由或元件載入樣式表。數值仍可取自共用 token;共用定義不代表必須將所有原生規則全域傳遞。

請先完成框架的安裝指南。Vite、Next.js 與 Webpack 整合讓這些區域樣式能使用專案 token、mixin 與自訂媒體:

  • app
    • globals.css
    • home
      • page.tsx
      • home.css

撰寫一般選擇器與宣告。數值需要在各頁保持一致時,請參照共用 token:

app/home/home.css
.home-section {  padding-block: var(--spacing-5xl);}

從負責該樣式的路由、頁面模組或元件進入點,載入路由樣式表:

app/home/page.tsx
import "./home.css"

請繼續從應用程式的共用外層載入全域樣式表,以提供串接層順序與共用樣式。全域樣式表從既有的 @import '@master/css' 開始;不要在 home.css 再加入這個完整匯入。

路由匯入控制的是傳遞方式,不是選擇器作用範圍。載入後,.home-section 可符合文件中任何具有該類別的元素。請用名稱表達負責範圍,需要區域作用範圍的類別名稱時,則使用框架的 CSS Modules 支援。框架也決定路由 CSS 的載入時機,以及導覽後是否保留。


載入路由樣式表不會限制選擇器作用範圍

匯入控制 CSS 的傳遞時機。載入後,原生類別選擇器可符合文件中的各個位置。

文字說明

路由檔案載入一條 .note 規則。文件中兩個區域都有符合的 .note 元素,兩者都被醒目標示。

#使用專案定義

共用定義,區域 CSS 傳遞

定義脈絡不會載入全域原生規則。框架負責傳遞路由 CSS,匯入不會隔離選擇器。

文字說明
  1. 參照. 編譯時讀取專案 token 與共用語彙。
  2. 編譯. 輸出路由原生規則及其使用的變數或受管理關鍵影格,不複製無關全域原生規則。
  3. 載入. 由框架或 bundler 傳遞路由 CSS 輸出。

整合會為區域樣式表提供專案定義脈絡。可在一般原生 CSS 中使用這些 token、mixin 與具名條件,生成樣式表的載入仍由框架負責。

app/home/home.css
.pricing-card {  padding: var(--spacing-lg);  border-radius: var(--radius-lg);  background-color: var(--color-surface-raised);}

路由輸出包含這些原生規則,以及它們使用的主題變數或受管理關鍵影格。即使其他進入點也使用相同資源,此輸出仍可獨立運作。全域原生規則與 utility 類別不會被複製進來。

#參照定義,不載入其原生規則

定義位於應用程式進入點相依圖之外時,請使用 @reference。例如,區域行銷樣式表可同時提供色彩 token 與自己的元件:

styles/marketing.css
@theme {  --color-campaign: var(--color-blue-60);}@layer components {  .campaign-root { color: var(--color-campaign); }}

從路由樣式表參照該檔案,再將其 token 用於路由負責的規則:

app/home/home.css
@reference "../../styles/marketing.css";@layer components {  .campaign-banner {    border-color: var(--color-campaign);  }}

路由輸出包含 .campaign-banner 與所需色彩資源,不包含 .campaign-root。若也需要該原生元件,請透過合適的應用程式或路由匯入來載入行銷樣式表。套件匯出的樣式表也適用相同區分。只提供定義的行為請參閱參照指令。


#撰寫原生選擇器

將路由原生規則寫在 app/home/home.css,再於路由標記中使用其類別。若要讓 utility 類別能覆寫個別選擇,請將規則放在 @layer components。

載入原生規則不會註冊新的 Master CSS utility。下方兩張卡片使用相同的原生類別,第二張加入 p-md,因此 utility 會覆寫元件的 var(--spacing-lg) 內距。這個類別名稱不需要註冊 @utility。

以區域 utility 調整路由 CSS

@layer components {  .home-bento {    display: grid;    gap: var(--spacing-md);    grid-template-columns: minmax(0, 1fr);    overflow-wrap: anywhere;  }  .home-bento-card {    border-radius: var(--radius-lg);    padding: var(--spacing-lg);    border: 1px solid var(--color-line-divider);    background-color: var(--color-surface-raised);    color: var(--color-text-body);  }  .home-bento-card > h2 {    font-size: var(--font-size-lg);    line-height: 1.4;    font-weight: var(--font-weight-regular);    margin-block: 0 0.5rem;  }  .home-bento-card > p {    color: var(--color-text-muted);    line-height: var(--leading-lg);    margin: 0;  }}
產生的 CSS
@layer components {  .home-bento {    gap: var(--spacing-md);    overflow-wrap: anywhere;    grid-template-columns: minmax(0, 1fr);    display: grid;  }  .home-bento-card {    border-radius: var(--radius-lg);    padding: var(--spacing-lg);    border: 1px solid var(--color-line-divider);    background-color: var(--color-surface-raised);    color: var(--color-text-body);  }  .home-bento-card > h2 {    font-size: var(--font-size-lg);    line-height: 1.4;    font-weight: var(--font-weight-regular);    margin-block: 0 .5rem;  }  .home-bento-card > p {    color: var(--color-text-muted);    line-height: var(--leading-lg);    margin: 0;  }}@layer theme {  :root,  :host {    --color-zinc-30: oklch(78% .0025 265);    --color-zinc-40: oklch(68.6% .0028 265);    --color-zinc-60: oklch(48.6% .003 265);    --color-zinc-70: oklch(39.8% .0028 265);    --color-zinc-90: oklch(24.6% .0022 265)  }  :root,  :host {    --color-surface-raised: light-dark(var(--color-white), var(--color-zinc-90));    --color-line-divider: light-dark(oklch(0% 0 none / .12), oklch(100% 0 none / .12));    --color-text-body: light-dark(var(--color-zinc-70), var(--color-zinc-30));    --color-text-muted: light-dark(var(--color-zinc-60), var(--color-zinc-40))  }  :root,  :host {    --color-white: oklch(100% 0 none)  }  :root,  :host {    --leading-lg: 1.8;    --font-weight-regular: 400;    --font-size-lg: 1.125rem;    --radius-lg: .5rem;    --spacing-md: 1rem;    --spacing-lg: 1.5rem  }}@layer utilities {  .p-md {    padding: var(--spacing-md)  }}
比較卡片內的空間。兩張卡片共用路由原生 CSS,只有第二張使用 utility 改變內距。

將規則保留在 @layer components,就能以類別覆寫;請參閱串接層。

這些原生規則預設會隨樣式表輸出。若來源明確啟用原生 CSS 修剪,偵測到的類別使用情況就會決定保留哪些規則。選擇器開始被多個頁面重用時,請將共用角色移至全域樣式。


#在區域樣式使用變體

專案自訂媒體可與一般媒體查詢一起用於原生規則中:

app/home/home.css
.home-note {  color: var(--color-blue-60);  @media (--dark) {    color: var(--color-blue-40);  }  @media (width < 52.125rem) {    width: 100%;  }}

--dark 遵循系統的 prefers-color-scheme 偏好。手動設定的 data-theme 屬性不會改變該查詢;表面若應跟隨手動選取的配色模式,請使用自適應色彩 token。

#驗證路由傳遞

先直接開啟路由,再從其他頁面導覽至該路由。檢查樣式表是否載入、原生選擇器是否符合,以及預期 token 值是否存在。也應檢查共用頁面:原始檔歸屬於區域,不應意外讓路由專用 CSS 進入應用程式進入點。

缺少輸出時,請檢查路由 CSS 匯入與整合的專案脈絡。規則存在但結果不同時,請檢查符合的選擇器、串接層與計算值。再加入一次完整 @master/css 匯入,無法修正選擇器或階層串接問題。

跨頁面比較前後測量、選擇性修剪與專案預算,請接著閱讀最佳化 CSS 傳遞。