Tailwind CSSCSSLayoutGrid前端開發2026

Tailwind 布局技巧:4 個讓你少寫 CSS 的方法

Tailwind CSS 布局完整教學!4 個少寫 CSS 的技巧、CSS 變數攻略、響應式布局密技。2026 年工程師必看的前端布局指南!

· 6 分鐘閱讀

如果你用 Tailwind CSS 超過三個月,你可能已經學會了 grid-cols-3gap-4md: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-8col-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);
}

陷阱二:frauto 混合時的行為

/* 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>

陷阱三:frminmax() 的組合

/* 陷阱: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?


延伸閱讀

本文是「2026 Tailwind CSS 實用技巧」系列文章之一。