核心概念
從一組有限的原始實用程式建構複雜的元件。
您可以使用 Tailwind 直接在您的標記中組合許多單一用途的呈現類別(實用類別)來設定樣式
您有新訊息!
<div class="mx-auto flex max-w-sm items-center gap-x-4 rounded-xl bg-white p-6 shadow-lg outline outline-black/5 dark:bg-slate-800 dark:shadow-none dark:-outline-offset-1 dark:outline-white/10"> <img class="size-12 shrink-0" src="/img/logo.svg" alt="ChitChat Logo" /> <div> <div class="text-xl font-medium text-black dark:text-white">ChitChat</div> <p class="text-gray-500 dark:text-gray-400">You have a new message!</p> </div></div>
例如,在上面的 UI 中,我們使用了
flex
、shrink-0
和 p-6
)來控制整體版面配置max-w-sm
和 mx-auto
)來限制卡片寬度並使其水平置中bg-white
、rounded-xl
和 shadow-lg
)來設定卡片外觀的樣式size-12
)來設定標誌圖片的寬度和高度gap-x-4
)來處理標誌和文字之間的間距text-xl
、text-black
、font-medium
等)來設定卡片文字的樣式以這種方式設定樣式與許多傳統的最佳實務做法相矛盾,但一旦您嘗試過,您會很快注意到一些非常重要的好處
這些好處在小型專案上產生很大的影響,但對於在大型長期專案上工作的團隊來說,它們更有價值。
對這種方法的一個常見反應是想知道「這不就是內嵌樣式嗎?」,在某些方面確實是 — 您是直接將樣式套用到元素,而不是為它們指定類別名稱,然後設定該類別的樣式。
但是,使用實用類別比內嵌樣式具有許多重要的優勢,例如
此元件具有完全響應式,並包含一個具有滑鼠懸停和啟用樣式的按鈕,完全使用工具類別建立
Erin Lindford
產品工程師
<div class="flex flex-col gap-2 p-8 sm:flex-row sm:items-center sm:gap-6 sm:py-4 ..."> <img class="mx-auto block h-24 rounded-full sm:mx-0 sm:shrink-0" src="/img/erin-lindford.jpg" alt="" /> <div class="space-y-2 text-center sm:text-left"> <div class="space-y-0.5"> <p class="text-lg font-semibold text-black">Erin Lindford</p> <p class="font-medium text-gray-500">Product Engineer</p> </div> <button class="border-purple-200 text-purple-600 hover:border-transparent hover:bg-purple-600 hover:text-white active:bg-purple-700 ..."> Message </button> </div></div>
若要設定元素在滑鼠懸停或焦點等狀態下的樣式,請在任何工具類別前加上您要鎖定的狀態,例如 hover:bg-sky-700
將滑鼠懸停在此按鈕上以查看背景顏色變化
<button class="bg-sky-500 hover:bg-sky-700 ...">Save changes</button>
這些前綴在 Tailwind 中稱為變體,它們僅在符合該變體的條件時才套用工具類別的樣式。
以下是 hover:bg-sky-700
類別產生的 CSS 外觀
.hover\:bg-sky-700 { &:hover { background-color: var(--color-sky-700); }}
注意到這個類別除非滑鼠懸停在元素上,否則不會執行任何動作嗎?它唯一的工作是提供滑鼠懸停樣式,沒有其他功能。
這與您編寫傳統 CSS 的方式不同,在傳統 CSS 中,單一類別通常會為許多狀態提供樣式
<button class="btn">Save changes</button><style> .btn { background-color: var(--color-sky-500); &:hover { background-color: var(--color-sky-700); } }</style>
您甚至可以在 Tailwind 中堆疊變體,以便在多個條件符合時套用工具,例如組合 hover:
和 disabled:
<button class="bg-sky-500 disabled:hover:bg-sky-500 ...">Save changes</button>
在滑鼠懸停、焦點和其他狀態的文件中了解更多有關樣式元素的資訊。
就像滑鼠懸停和焦點狀態一樣,您可以透過在任何工具前加上您要套用樣式的斷點,來設定元素在不同斷點下的樣式
調整此範例的大小以查看版面配置的變更
<div class="grid grid-cols-2 sm:grid-cols-3"> <!-- ... --></div>
在上面的範例中,sm:
前綴確保 grid-cols-3
僅在 sm
斷點及以上觸發,預設值為 40rem
.sm\:grid-cols-3 { @media (width >= 40rem) { grid-template-columns: repeat(3, minmax(0, 1fr)); }}
在響應式設計文件中了解更多資訊。
設定元素在深色模式下的樣式,只需在任何您想要在深色模式啟用時套用的工具中加上 dark:
前綴即可
淺色模式
倒著寫
零重力筆可以用於以任何方向書寫,包括倒著寫。它甚至可以在外太空運作。
深色模式
倒著寫
零重力筆可以用於以任何方向書寫,包括倒著寫。它甚至可以在外太空運作。
<div class="bg-white dark:bg-gray-800 rounded-lg px-6 py-8 ring shadow-xl ring-gray-900/5"> <div> <span class="inline-flex items-center justify-center rounded-md bg-indigo-500 p-2 shadow-lg"> <svg class="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true" > <!-- ... --> </svg> </span> </div> <h3 class="text-gray-900 dark:text-white mt-5 text-base font-medium tracking-tight ">Writes upside-down</h3> <p class="text-gray-500 dark:text-gray-400 mt-2 text-sm "> The Zero Gravity Pen can be used to write in any orientation, including upside-down. It even works in outer space. </p></div>
就像滑鼠懸停狀態或媒體查詢一樣,重要的是要了解單一工具類別永遠不會包含淺色和深色樣式,您是透過使用多個類別來設定深色模式下的樣式,一個用於淺色模式樣式,另一個用於深色模式樣式。
.dark\:bg-gray-800 { @media (prefers-color-scheme: dark) { background-color: var(--color-gray-800); }}
在深色模式文件中了解更多資訊。
在 Tailwind 中,您經常會使用多個類別來建立單一 CSS 屬性的值,例如將多個篩選器加入元素
<div class="blur-sm grayscale"> <!-- ... --></div>
這兩種效果都依賴 CSS 中的 filter
屬性,因此 Tailwind 使用 CSS 變數來讓這些效果可以組合在一起
.blur-sm { --tw-blur: blur(var(--blur-sm)); filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-grayscale,);}.grayscale { --tw-grayscale: grayscale(100%); filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-grayscale,);}
上面產生的 CSS 稍微簡化,但這裡的訣竅是每個工具都會為它要套用的效果設定一個 CSS 變數。然後,filter
屬性會查看所有這些變數,如果沒有設定變數,則會回復為無。
Tailwind 對於漸層、陰影顏色、轉換等也使用相同的方法。
Tailwind 中的許多工具都由主題變數驅動,例如 bg-blue-500
、text-xl
和 shadow-md
,這些變數會對應到您底層的調色盤、類型比例和陰影。
當您需要使用主題以外的一次性值時,請使用特殊方括號語法來指定任意值
<button class="bg-[#316ff6] ..."> Sign in with Facebook</button>
這對於調色盤之外的一次性顏色(例如上面的 Facebook 藍色)很有用,當您需要複雜的自訂值(例如非常特定的網格)時也很有用
<div class="grid grid-cols-[24rem_2.5rem_minmax(0,1fr)]"> <!-- ... --></div>
當您需要使用 CSS 功能(例如 calc()
)時,即使您正在使用主題值,它也很有用
<div class="max-h-[calc(100dvh-(--spacing(6))]"> <!-- ... --></div>
甚至有一種語法可以產生完全任意的 CSS,包括任意屬性名稱,這對於設定 CSS 變數很有用
<div class="[--gutter-width:1rem] lg:[--gutter-width:2rem]"> <!-- ... --></div>
在使用任意值的文件中了解更多資訊。
Tailwind CSS 並不像您可能習慣使用的其他 CSS 框架那樣是一個大型的靜態樣式表,它會根據您在編譯 CSS 時實際使用的類別產生所需的 CSS。
它會掃描您專案中的所有檔案,尋找任何看起來像是類別名稱的符號,來執行此操作
export default function Button({ size, children }) { let sizeClasses = { md: "px-4 py-2 rounded-md text-base", lg: "px-5 py-3 rounded-lg text-lg", }[size]; return ( <button type="button" className={`font-bold ${sizeClasses}`}> {children} </button> );}
找到所有潛在的類別後,Tailwind 會為每個類別產生 CSS,並將它們全部編譯成一個僅包含您實際需要樣式的樣式表。
由於 CSS 是根據類別名稱產生的,因此 Tailwind 可以辨識使用任意值的類別(例如 bg-[#316ff6]
),並產生必要的 CSS,即使該值不是您主題的一部分。
在偵測來源檔案中的類別中了解更多關於其運作方式的資訊。
有時您需要設定元素在多種條件下的樣式,例如在深色模式下、在特定斷點下、當滑鼠懸停時,以及當元素具有特定資料屬性時。
以下是使用 Tailwind 時的外觀範例
<button class="dark:lg:data-current:hover:bg-indigo-600 ..."> <!-- ... --></button>
@media (prefers-color-scheme: dark) and (width >= 64rem) { button[data-current]:hover { background-color: var(--color-indigo-600); }}
Tailwind 也支援 group-hover
等功能,讓您可以在滑鼠懸停在特定父元素上時設定元素的樣式
<a href="#" class="group rounded-lg p-8"> <!-- ... --> <span class="group-hover:underline">Read more…</span></a>
@media (hover: hover) { a:hover span { text-decoration-line: underline; }}
這種 group-*
語法也適用於其他變體,例如 group-focus
、group-active
和更多。
對於非常複雜的案例(尤其是在設定您無法控制的 HTML 樣式時),Tailwind 支援任意變體,讓您可以直接在類別名稱中撰寫任何想要的選取器
<div class="[&>[data-active]+span]:text-blue-600 ..."> <span data-active><!-- ... --></span> <span>This text will be blue</span></div>
div > [data-active] + span { color: var(--color-blue-600);}
行內樣式在 Tailwind CSS 專案中仍然非常有用,尤其是在值來自資料庫或 API 等動態來源時
export function BrandedButton({ buttonColor, textColor, children }) { return ( <button style={{ backgroundColor: buttonColor, color: textColor, }} className="rounded-md px-3 py-1.5 font-medium" > {children} </button> );}
您也可以使用行內樣式來處理非常複雜的任意值,這些值在格式化為類別名稱時難以閱讀
<div class="grid-[2fr_max(0,var(--gutter-width))_calc(var(--gutter-width)+10px)]"><div style="grid-template-columns: 2fr max(0, var(--gutter-width)) calc(var(--gutter-width) + 10px)"> <!-- ... --></div>
另一個有用的模式是使用行內樣式根據動態來源設定 CSS 變數,然後使用工具類別參照這些變數
export function BrandedButton({ buttonColor, buttonColorHover, textColor, children }) { return ( <button style={{ "--bg-color": buttonColor, "--bg-color-hover": buttonColorHover, "--text-color": textColor, }} className="bg-(--bg-color) text-(--text-color) hover:bg-(--bg-color-hover) ..." > {children} </button> );}
當您僅使用工具類別來建置整個專案時,您將不可避免地發現自己重複某些模式,以在不同位置重新建立相同的設計。
例如,這裡每個頭像圖片的工具類別都重複了五次
<div> <div class="flex items-center space-x-2 text-base"> <h4 class="font-semibold text-slate-900">Contributors</h4> <span class="bg-slate-100 px-2 py-1 text-xs font-semibold text-slate-700 ...">204</span> </div> <div class="mt-3 flex -space-x-2 overflow-hidden"> <img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" /> <img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" /> <img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2.25&w=256&h=256&q=80" alt="" /> <img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" /> <img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1517365830460-955ce3ccd263?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" /> </div> <div class="mt-3 text-sm font-medium"> <a href="#" class="text-blue-500">+ 198 others</a> </div></div>
別慌!實際上這並不是你擔心的問題,而且解決策略都是你每天都在做的事情。
很多時候,在渲染頁面中多次出現的設計元素實際上只被撰寫一次,因為實際的標記是在迴圈中渲染的。
例如,本指南開頭重複出現的頭像,在真實專案中幾乎肯定會在迴圈中渲染。
<div> <div class="flex items-center space-x-2 text-base"> <h4 class="font-semibold text-slate-900">Contributors</h4> <span class="bg-slate-100 px-2 py-1 text-xs font-semibold text-slate-700 ...">204</span> </div> <div class="mt-3 flex -space-x-2 overflow-hidden"> {#each contributors as user} <img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src={user.avatarUrl} alt={user.handle} /> {/each} </div> <div class="mt-3 text-sm font-medium"> <a href="#" class="text-blue-500">+ 198 others</a> </div></div>
當元素像這樣在迴圈中渲染時,實際的類別列表只會被寫入一次,因此實際上沒有重複的問題需要解決。
當重複出現在單一檔案中的一組元素中時,最簡單的處理方法是使用多重游標編輯,快速選取並同時編輯每個元素的類別列表。
你可能會驚訝地發現,這最終往往是最好的解決方案。如果你可以快速地同時編輯所有重複的類別列表,就沒有必要引入任何額外的抽象。
<nav class="flex justify-center space-x-4"> <a href="/dashboard" class="font-medium rounded-lg px-3 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-900"> Home </a> <a href="/team" class="font-medium rounded-lg px-3 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-900"> Team </a> <a href="/projects" class="font-medium rounded-lg px-3 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-900"> Projects </a> <a href="/reports" class="font-medium rounded-lg px-3 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-900"> Reports </a></nav>
如果你需要在多個檔案中重複使用某些樣式,最好的策略是建立一個元件,如果你使用的是像 React、Svelte 或 Vue 等前端框架,或者建立一個樣板局部,如果你使用的是像 Blade、ERB、Twig 或 Nunjucks 等樣板語言。
export function VacationCard({ img, imgAlt, eyebrow, title, pricing, url }) { return ( <div> <img className="rounded-lg" src={img} alt={imgAlt} /> <div className="mt-4"> <div className="text-xs font-bold text-sky-500">{eyebrow}</div> <div className="mt-1 font-bold text-gray-700"> <a href={url} className="hover:underline"> {title} </a> </div> <div className="mt-2 text-sm text-gray-600">{pricing}</div> </div> </div> );}
現在你可以在任何地方使用這個元件,同時仍然有一個樣式的單一來源,以便可以在一個地方輕鬆更新。
如果你使用的是像 ERB 或 Twig 這樣的樣板語言,而不是像 React 或 Vue 這樣的東西,那麼為像按鈕這樣小的東西建立樣板局部,與簡單的 CSS 類別(例如 btn
)相比,可能會感覺有點小題大作。
雖然強烈建議你為更複雜的元件建立適當的樣板局部,但當樣板局部感覺太笨重時,編寫一些自訂 CSS 也是完全可以的。
以下是一個 btn-primary
類別的範例,使用主題變數來保持設計的一致性
<button class="btn-primary">Save changes</button> Save changes</button>
@import "tailwindcss";@layer components { .btn-primary { border-radius: calc(infinity * 1px); background-color: var(--color-violet-500); padding-inline: --spacing(5); padding-block: --spacing(2); font-weight: var(--font-weight-semibold); color: var(--color-white); box-shadow: var(--shadow-md); &:hover { @media (hover: hover) { background-color: var(--color-violet-700); } } }}
但同樣地,對於任何比單一 HTML 元素更複雜的東西,我們強烈建議使用樣板局部,以便將樣式和結構封裝在一個地方。