繁體中文English
jason's blog關於網頁標準、瀏覽器與前端開發的觀察筆記

文章分類: CSS

Tailwind CSS v4 的 CSS-first 設定方式

從設定檔搬進 CSS,看看 Tailwind CSS v4 的 CSS-first 到底改變了什麼。

發布 2025/01/21

我第一次看到 Tailwind v4 把設定搬進 CSS 時,其實愣了一下:繞了這麼多年,怎麼又回到 CSS 了?再看幾次才發現,它不是要否定 utility class,反而像是終於承認顏色、字型和間距本來就屬於 CSS 的語境。這個改動沒有新元件那麼搶眼,卻是我讀完整份更新後最想拿來試的部分。

Tailwind CSS v4 有個很明顯的改變:以前常放在 tailwind.config.js 裡的顏色、字型和斷點,現在可以直接寫在 CSS 裡。官方把這種方向叫做 CSS-first。

例如網站有一個品牌色,可以在 @theme 裡建立 --color-brand,接著在畫面上使用 text-brandbg-brand。設定和實際產生的 CSS 變數放得更近,看起來也比較直覺。

這不代表 Tailwind 放棄 utility class,也不是叫大家回去手寫所有 CSS。真正的差別只是「設定 Tailwind 的地方」從 JavaScript 搬到 CSS。對新專案來說少了一份設定檔;舊專案則不用為了跟上潮流急著重寫,先確認現有 plugin 和客製設定是否相容即可。

設定搬進 CSS 之後

假設網站有自己的品牌色,v3 常見的做法是在 JavaScript config 裡擴充 theme;v4 可以直接這樣寫:

@import "tailwindcss";
 
@theme {
  --color-brand: #173f76;
  --font-display: Georgia, serif;
}

Tailwind 看到這些變數後,會產生 bg-brandtext-brandfont-display。好處不只少一個設定檔,這些 token 也能直接用 var(--color-brand) 交給一般 CSS 或動畫套件。

@theme 和普通的 :root 也不完全一樣。放在 :root 的變數只是一般 CSS custom property,不會自動產生 Tailwind utility;放在 @theme 的 token 才會參與 Tailwind 的 class 生成。單純給既有 CSS 使用的變數,仍然放在 :root 就好,不需要把所有數值都塞進 theme。

有個小地方要釐清:@theme 長得像 CSS,但它仍是 Tailwind 的建置指令,不是瀏覽器原生功能。以後若拿掉 Tailwind,這部分還是要改。CSS-first 比較像是讓設定回到 CSS 的語境,不代表框架依賴消失了。

我自己比較喜歡 v4 的地方,是在 code review 裡終於比較容易回答「這個顏色從哪裡來」。以前常要先看到 bg-brand,再跳去 JavaScript 設定檔找對應值;現在 token、一般 CSS 和 utility 之間的距離短很多。這不是什麼效能上的大突破,但對每天要讀程式的人很實在。

不過我還是會克制 theme 的大小。設計稿出現一次的 17px 間距,不一定值得立刻變成全域 token;否則幾個月後,--spacing-card-small--spacing-card-smaller 一樣會變成另一種設定檔地獄。CSS-first 讓新增 token 更方便,也更需要團隊先約定什麼東西才算設計系統的一部分。