核心概念(Core Concepts)
在 Tailwind 專案中新增自訂樣式的最佳實務。
使用框架時,最大的挑戰通常是弄清楚當你需要某些框架沒有處理的功能時該怎麼辦。
Tailwind 從一開始就被設計成可擴展和可自訂的,這樣無論你在建構什麼,都不會感覺在與框架對抗。
本指南涵蓋了自訂設計代碼、必要時如何突破這些限制、新增自訂 CSS,以及透過插件擴展框架等主題。
如果你想要變更色彩調色盤、間距比例、字型比例或斷點等設定,請在 CSS 中使用 @theme 指令新增你的自訂設定:
@theme { --font-display: "Satoshi", "sans-serif"; --breakpoint-3xl: 120rem; --color-avocado-100: oklch(0.99 0 0); --color-avocado-200: oklch(0.98 0.04 113.22); --color-avocado-300: oklch(0.94 0.11 115.03); --color-avocado-400: oklch(0.92 0.19 114.08); --color-avocado-500: oklch(0.84 0.18 117.33); --color-avocado-600: oklch(0.53 0.12 118.34); --ease-fluid: cubic-bezier(0.3, 0, 0, 1); --ease-snappy: cubic-bezier(0.2, 0, 0, 1); /* ... */}在主題變數文件中了解更多關於自訂主題的資訊。
雖然你通常可以使用一組受限的設計代碼來建構大部分精心設計的版面,但偶爾你還是需要突破這些限制來達到完美的像素精準度。
當你發現自己真的需要像 top: 117px 這樣的值來讓背景圖片定位在正確的位置時,使用 Tailwind 的方括號語法即時產生具有任意值的類別:
<div class="top-[117px]"> <!-- ... --></div>這基本上就像內聯樣式,但最大的好處是你可以將它與 hover 這樣的互動修飾符和 lg 這樣的響應式修飾符結合使用:
<div class="top-[117px] lg:top-[344px]"> <!-- ... --></div>這適用於框架中的所有內容,包括背景顏色、字型大小、偽元素內容等等:
<div class="bg-[#bada55] text-[22px] before:content-['Festivus']"> <!-- ... --></div>如果你將 CSS 變數作為任意值參照,可以使用自訂屬性語法:
<div class="fill-(--my-brand-color) ..."> <!-- ... --></div>這只是 fill-[var(--my-brand-color)] 的簡寫,它會自動為你新增 var() 函式。
如果你需要使用 Tailwind 沒有內建通用類別的 CSS 屬性,你也可以使用方括號語法來撰寫完全任意的 CSS:
<div class="[mask-type:luminance]"> <!-- ... --></div>這_真的_很像內聯樣式,但同樣具有可以使用修飾符的好處:
<div class="[mask-type:luminance] hover:[mask-type:alpha]"> <!-- ... --></div>這對於像 CSS 變數這樣的東西也很有用,特別是當它們需要在不同條件下改變時:
<div class="[--scroll-offset:56px] lg:[--scroll-offset:44px]"> <!-- ... --></div>任意_變體_類似於任意值,但用於即時修改選擇器,就像你可以使用內建的偽類別變體(如 hover:{utility})或響應式變體(如 md:{utility})一樣,但直接在 HTML 中使用方括號語法。
<ul role="list"> {#each items as item} <li class="lg:[&:nth-child(-n+3)]:hover:underline">{item}</li> {/each}</ul>在任意變體文件中了解更多。
當任意值需要包含空格時,使用底線(_)代替,Tailwind 會在建構時自動將其轉換為空格:
<div class="grid grid-cols-[1fr_500px_2fr]"> <!-- ... --></div>在底線很常見但空格無效的情況下,Tailwind 會保留底線而不是將其轉換為空格,例如在 URL 中:
<div class="bg-[url('/what_a_rush.png')]"> <!-- ... --></div>在極少數情況下,你確實需要使用底線,但由於空格也有效而造成歧義時,請用反斜線跳脫底線,Tailwind 就不會將其轉換為空格:
<div class="before:content-['hello\_world']"> <!-- ... --></div>如果你使用像 JSX 這樣會從渲染的 HTML 中移除反斜線的工具,請使用 String.raw(),這樣反斜線就不會被視為 JavaScript 跳脫字元:
<div className={String.raw`before:content-['hello\_world']`}> <!-- ... --></div>Tailwind 中的許多通用類別共享相同的命名空間,但對應到不同的 CSS 屬性。例如 text-lg 和 text-black 都共享 text- 命名空間,但一個是用於 font-size,另一個是用於 color。
當使用任意值時,Tailwind 通常可以根據你傳入的值自動處理這種歧義:
<!-- 將產生字型大小通用類別 --><div class="text-[22px]">...</div><!-- 將產生顏色通用類別 --><div class="text-[#bada55]">...</div>但有時候確實會有歧義,例如使用 CSS 變數時:
<div class="text-(--my-var)">...</div>在這些情況下,你可以透過在值前面新增 CSS 資料型別來向 Tailwind「提示」底層型別:
<!-- 將產生字型大小通用類別 --><div class="text-(length:--my-var)">...</div><!-- 將產生顏色通用類別 --><div class="text-(color:--my-var)">...</div>雖然 Tailwind 旨在處理大部分的樣式需求,但當你需要時,沒有什麼能阻止你直接撰寫純 CSS:
@import "tailwindcss";.my-custom-style { /* ... */}如果你只是想為頁面設定一些預設值(像是文字顏色、背景顏色或字型),最簡單的方法就是在 html 或 body 元素上新增一些類別:
<!doctype html><html lang="en" class="bg-gray-100 font-serif text-gray-900"> <!-- ... --></html>這樣可以讓你的基礎樣式決策與所有其他樣式一起保留在標記中,而不是藏在單獨的檔案裡。
如果你想為特定的 HTML 元素新增自己的預設基礎樣式,請使用 @layer 指令將這些樣式新增到 Tailwind 的 base 層:
@layer base { h1 { font-size: var(--text-2xl); } h2 { font-size: var(--text-xl); }}使用 components 層來新增任何你想加入專案的更複雜類別,同時仍然希望能夠用通用類別覆寫它們。
傳統上這些會是像 card、btn、badge 這樣的類別——諸如此類。
@layer components { .card { background-color: var(--color-white); border-radius: var(--radius-lg); padding: --spacing(6); box-shadow: var(--shadow-xl); }}透過在 components 層中定義元件類別,你仍然可以在必要時使用通用類別覆寫它們:
<!-- 看起來像卡片,但有方角 --><div class="card rounded-none"> <!-- ... --></div>使用 Tailwind 時,你可能不需要像你想像的那樣經常使用這類類別。閱讀我們關於管理重複的指南以了解我們的建議。
components 層也是放置任何你正在使用的第三方元件自訂樣式的好地方:
@layer components { .select2-dropdown { /* ... */ }}使用 @variant 指令在自訂 CSS 中套用 Tailwind 變體:
.my-element { background: white; @variant dark { background: black; }}.my-element { background: white; @media (prefers-color-scheme: dark) { background: black; }}如果你需要同時套用多個變體,請使用巢狀:
.my-element { background: white; @variant dark { @variant hover { background: black; } }}.my-element { background: white; @media (prefers-color-scheme: dark) { &:hover { @media (hover: hover) { background: black; } } }}除了使用 Tailwind 內建的通用類別外,你還可以新增自己的自訂通用類別。當有一個你想在專案中使用但 Tailwind 沒有內建通用類別的 CSS 功能時,這會很有用。
使用 @utility 指令將自訂通用類別新增到你的專案:
@utility content-auto { content-visibility: auto;}現在你可以在 HTML 中使用這個通用類別:
<div class="content-auto"> <!-- ... --></div>它也可以與 hover、focus 和 lg 等變體一起使用:
<div class="hover:content-auto"> <!-- ... --></div>自訂通用類別會自動插入到 utilities 層,與框架中所有內建的通用類別一起。
如果你的自訂通用類別比單一類別名稱更複雜,請使用巢狀來定義通用類別:
@utility scrollbar-hidden { &::-webkit-scrollbar { display: none; }}除了使用 @utility 指令註冊簡單的通用類別外,你還可以註冊接受參數的函式型通用類別:
@utility tab-* { tab-size: --value(--tab-size-*);}特殊的 --value() 函式用於解析通用類別的值。
使用 --value(--theme-key-*) 語法根據一組主題鍵來解析通用類別的值:
@theme { --tab-size-2: 2; --tab-size-4: 4; --tab-size-github: 8;}@utility tab-* { tab-size: --value(--tab-size-*);}這將比對像 tab-2、tab-4 和 tab-github 這樣的通用類別。
要將值解析為裸值,請使用 --value({type}) 語法,其中 {type} 是你想要驗證裸值的資料型別:
@utility tab-* { tab-size: --value(integer);}這將比對像 tab-1 和 tab-76 這樣的通用類別。
可用的裸值資料型別有:number、integer、ratio 和 percentage。
要支援字面值,請使用 --value('literal') 語法(注意引號):
@utility tab-* { tab-size: --value("inherit", "initial", "unset");}這將比對像 tab-inherit、tab-initial 和 tab-unset 這樣的通用類別。
要支援任意值,請使用 --value([{type}]) 語法(注意方括號)來告訴 Tailwind 哪些型別可作為任意值使用:
@utility tab-* { tab-size: --value([integer]);}這將比對像 tab-[1] 和 tab-[76] 這樣的通用類別。
可用的任意值資料型別有:absolute-size、angle、bg-size、color、family-name、generic-name、image、integer、length、line-width、number、percentage、position、ratio、relative-size、url、vector 和 *。
--value() 函式的三種形式都可以在規則中作為多個宣告使用,任何無法解析的宣告都會在輸出中省略:
@theme { --tab-size-github: 8;}@utility tab-* { tab-size: --value([integer]); tab-size: --value(integer); tab-size: --value(--tab-size-*);}如有必要,這使得可以在每種情況下以不同方式處理值,例如將裸整數轉換為百分比:
@utility opacity-* { opacity: --value([percentage]); opacity: calc(--value(integer) * 1%); opacity: --value(--opacity-*);}--value() 函式也可以接受多個參數,如果你不需要在不同情況下以不同方式處理回傳值,它會從左到右解析它們:
@theme { --tab-size-github: 8;}@utility tab-* { tab-size: --value(--tab-size-*, integer, [integer]);}@utility opacity-* { opacity: calc(--value(integer) * 1%); opacity: --value(--opacity-*, [percentage]);}要支援負值,請將正值和負值的通用類別分別註冊到不同的宣告中:
@utility inset-* { inset: --spacing(--value(integer)); inset: --value([percentage], [length]);}@utility -inset-* { inset: --spacing(--value(integer) * -1); inset: calc(--value([percentage], [length]) * -1);}修飾符使用 --modifier() 函式處理,它的運作方式與 --value() 函式完全相同,但在存在修飾符時對修飾符進行操作:
@utility text-* { font-size: --value(--text-*, [length]); line-height: --modifier(--leading-*, [length], [*]);}如果修飾符不存在,任何依賴修飾符的宣告都不會包含在輸出中。
要處理分數,我們依賴 CSS ratio 資料型別。如果與 --value() 一起使用,這會向 Tailwind 發出信號,將值和修飾符視為單一值:
@utility aspect-* { aspect-ratio: --value(--aspect-ratio-*, ratio, [ratio]);}這將比對像 aspect-square、aspect-3/4 和 aspect-[7/9] 這樣的通用類別。
除了使用 Tailwind 內建的變體外,你還可以使用 @custom-variant 指令新增自己的自訂變體:
@custom-variant theme-midnight { &:where([data-theme="midnight"] *) { @slot; }}現在你可以在 HTML 中使用 theme-midnight:<utility> 變體:
<html data-theme="midnight"> <button class="theme-midnight:bg-black ..."></button></html>當不需要巢狀時,你可以使用簡寫語法建立變體:
@custom-variant theme-midnight (&:where([data-theme="midnight"] *));當自訂變體有多個規則時,它們可以互相巢狀:
@custom-variant any-hover { @media (any-hover: hover) { &:hover { @slot; } }}