📋 目錄
如果你用 Tailwind CSS 超過三個月,你可能已經學會了
grid-cols-3、gap-4、md:col-span-2這些基本用法。但 Tailwind 的布局能力遠不止這些。這篇文章整理了 4 個可以實質減少你 CSS 程式碼量的 Tailwind 布局技巧——從 CSS 變數的創意用法,到響應式布局的最後一哩。
技巧一:CSS 變數讓布局可讀性更高
過去的方式
<!-- 需要記憶每個數字的含義 -->
<div class="grid grid-cols-12 gap-6">
<div class="col-span-8">主要內容</div>
<div class="col-span-4">側邊欄</div>
</div>
col-span-8 和 col-span-4 是什麼意思?8/12 是什麼比例?側邊欄是 4/12?每次看到這個佈局都要在腦中計算。
CSS 變數的方式
<!-- 意圖更明確 -->
<div class="grid gap-6" style="grid-template-columns: repeat(var(--main-cols, 8), 1fr) var(--sidebar-cols, 4);">
<div class="col-span-var(--main-cols, 8)">主要內容</div>
<div class="col-span-var(--sidebar-cols, 4)">側邊欄</div>
</div>
但更好的方式是這樣的語法糖:
<div class="grid" style="--cols: 3;">
<div style="grid-column: span var(--cols);"></div>
</div>
實際應用
<!-- 定義一個「文章卡片網格」的 component -->
<div
class="grid gap-6"
style="
--card-cols: 2;
--gap-x: 24px;
--gap-y: 16px;
grid-template-columns: repeat(var(--card-cols), 1fr);
"
>
<!-- 每張卡片的 col-span 可以用 CSS 變數控制 -->
<article class="card" style="grid-column: span var(--card-cols, 1);">
<h2>Featured Article</h2>
<p>This card spans the full width.</p>
</article>
<article class="card">
<h2>Regular Card</h2>
</article>
<article class="card">
<h2>Regular Card</h2>
</article>
</div>
技巧二:不用命名布局類別
過去的命名地獄
在傳統 CSS 架構裡,你可能會寫這樣的 class:
.layout-sidebar { display: grid; grid-template-columns: 250px 1fr; gap: 24px; }
.layout-three-col { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 24px; }
.layout-hero { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; }
每一個新的佈局都要發明一個新名字,然後牢記它。
Tailwind 的數字法
<!-- 不用命名,用數字 -->
<div class="grid grid-cols-12 gap-6">
<!-- 三欄佈局:3 + 6 + 3 = 12 -->
<div class="col-span-3">左側欄</div>
<div class="col-span-6">主要內容</div>
<div class="col-span-3">右側欄</div>
</div>
<!-- 改變比例:2 + 8 = 10,不是 12 -->
<div class="grid grid-cols-10 gap-6">
<div class="col-span-2">窄側邊欄</div>
<div class="col-span-8">主要內容</div>
</div>
<!-- 用 5 欄系統:2 + 1 + 2 -->
<div class="grid grid-cols-5 gap-4">
<div class="col-span-2">左區塊</div>
<div class="col-span-1">中間</div>
<div class="col-span-2">右區塊</div>
</div>
不用在乎命名,只在乎比例。
技巧三:情境式布局變化——同一結構,不同間距
問題
同一個「兩欄佈局」,在手機上你需要 gap-4,在平板上需要 gap-6,在桌面需要 gap-8:
<!-- 過去:每個 breakpoint 都要重複定義 -->
<div class="grid grid-cols-2 gap-4 md:gap-6 lg:gap-8">
<div>Card 1</div>
<div>Card 2</div>
</div>
這還不算糟糕——但當你有 10 個不同的佈局組件,每個都要維護這套 gap 版本時,CSS 會快速失控。
CSS 變數的解法
<!-- 一次定義,到處使用 -->
<div class="grid gap-[var(--grid-gap)]" style="--grid-gap: 16px;">
<div>Card 1</div>
<div>Card 2</div>
</div>
<!-- 在不同的 container 上調整 -->
<section class="compact-grid" style="--grid-gap: 8px;">
<!-- 這個 grid 的 gap 會是 8px -->
<div class="grid gap-[var(--grid-gap)]">
<div>Card 1</div>
<div>Card 2</div>
</div>
</section>
<section class="spacious-grid" style="--grid-gap: 32px;">
<!-- 這個 grid 的 gap 會是 32px -->
<div class="grid gap-[var(--grid-gap)]">
<div>Card 1</div>
<div>Card 2</div>
</div>
</section>
響應式調整的最後一哩
用 [md]: 之類的任意值語法,即時覆蓋:
<!-- 默認間距是 16px,但從 md 開始變成 24px -->
<div class="grid gap-4 md:[--grid-gap:24px]">
<!-- 使用 CSS 變數的 gap -->
<div class="grid gap-[var(--grid-gap)]">
<div>Card</div>
<div>Card</div>
</div>
</div>
技巧四:fr 單位的陷阱
fr 單位是什麼
fr(fraction)是 CSS Grid 的單位,表示「可用空間的分數」:
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
/* 等於 50% 50% */
}
陷阱一:2fr 1fr 不等於三欄
/* 這個佈局只有 2 欄,不是 3 欄 */
.grid {
display: grid;
grid-template-columns: 2fr 1fr;
/* 2fr + 1fr = 3fr,但只有 2 個元素 */
}
如果你想要三欄,你應該這樣寫:
/* 正確:明確指定 3 欄 */
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
/* 或 */
grid-template-columns: repeat(3, 1fr);
}
陷阱二:fr 與 auto 混合時的行為
/* sidebar 佔 250px,主要區域佔剩餘空間 */
.grid {
display: grid;
grid-template-columns: 250px 1fr;
/* 1fr = 總寬度 - 250px */
}
<!-- 用 Tailwind 寫 -->
<div class="grid" style="grid-template-columns: 250px 1fr;">
<div>Sidebar (250px)</div>
<div>Main (remaining)</div>
</div>
<!-- 或用 Tailwind 的內建 class -->
<div class="grid grid-cols-[250px_1fr]">
<div>Sidebar</div>
<div>Main</div>
</div>
陷阱三:fr 與 minmax() 的組合
/* 陷阱:minmax(0, 1fr) vs 1fr */
.grid-bad {
grid-template-columns: minmax(0, 1fr) 1fr;
/* 第一欄有 min size 0,所以可能為 0 */
}
.grid-good {
grid-template-columns: 1fr 1fr;
/* 兩個欄位均分 */
}
Tailwind 處理這個問題的方式是盡量讓你用數字和比例,而不是直接寫 fr:
<!-- Tailwind 盡量讓你用這些 -->
<div class="grid grid-cols-2 gap-4"> <!-- 2 等分 -->
<div class="grid grid-cols-3 gap-4"> <!-- 3 等分 -->
<div class="grid grid-cols-4 gap-4"> <!-- 4 等分 -->
實際案例:重構一個 Dashboard 布局
重構前:傳統 CSS
.sidebar { width: 250px; flex-shrink: 0; }
.main-content { flex: 1; min-width: 0; }
.grid-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.grid-cards-compact { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
@media (max-width: 768px) {
.sidebar { width: 100%; }
.grid-cards { grid-template-columns: 1fr; }
}
重構後:Tailwind + CSS 變數
<div class="flex gap-6">
<!-- Sidebar -->
<aside class="w-[250px] shrink-0 hidden md:block">
<nav class="sticky top-4">
<!-- Nav items -->
</nav>
</aside>
<!-- Main content -->
<main class="flex-1 min-w-0">
<!-- 三欄卡片網格 -->
<div
class="grid gap-6"
style="grid-template-columns: repeat(var(--card-cols, 3), 1fr);"
>
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
</div>
<!-- 四欄緊密網格(在不同的 section) -->
<section style="--card-cols: 4; --card-gap: 16px;">
<div
class="grid gap-[var(--card-gap)]"
style="grid-template-columns: repeat(var(--card-cols), 1fr);"
>
<div class="card">Compact Card 1</div>
<div class="card">Compact Card 2</div>
<div class="card">Compact Card 3</div>
<div class="card">Compact Card 4</div>
</div>
</section>
</main>
</div>
CSS 行數:從 20+ 行 → 0 行(除了必要的 flex 屬性)
結語:布局的未來是宣告式
這四個技巧的共同方向是:從「用 CSS 描述布局」走向「用宣告式語法定義布局」。
- CSS 變數讓布局參數可以在 DOM 層級繼承和覆蓋
- 數字代替命名減少了認知負擔
- 情境式變化讓同一個結構可以在不同環境有不同的表現
下次當你發現自己在重複定義相似但稍微不同的佈局時,問自己:這些差異能否用 CSS 變數來表達,而不是寫更多 CSS class?
延伸閱讀
- Tailwind CSS 4.0 — Tailwind 最新版本
- CSS 2026 進化論 — CSS 最新功能總覽
本文是「2026 Tailwind CSS 實用技巧」系列文章之一。