TailwindCSS Layout 與 Display:block、flex、grid、overflow、object-fit 全解析 | TailwindCSS 完整教學
在 TailwindCSS 裡,Layout 與 display 是版面的骨架——
block、inline、flex、grid決定元素怎麼排列,hidden決定它出不出現,overflow決定內容溢出時怎麼處理,object-fit決定圖片如何填滿容器。這篇是 TailwindCSS 完整教學 系列的第八篇,也是版面章節(TW-3)的開場,我們會把這一整組「掌控排列方式」的工具類一次講透,並以 v4 為預設、標註每一項與 v3 的差異。
前言
Layout(版面) 在網頁裡指的是「元素如何在頁面上排列與佔位」的一整套規則——它該獨佔一行還是跟旁邊擠在一起、它是一個 Flex 容器還是 Grid 容器、內容太多溢出時要裁掉還是加捲軸、圖片要如何填進固定尺寸的框裡。這一切的最底層,是一個叫做 display 的 CSS 屬性:它決定了一個元素的「渲染模式」,也就是這個盒子到底用哪一套規則來排版。在傳統 CSS 裡,這些由 display、overflow、object-fit、aspect-ratio、columns、box-sizing、float 等屬性分別掌管;而 TailwindCSS 的版面系統,就是把這些屬性一對一包裝成好記、可組合的 utility class。
用一個現實世界的類比來理解:如果說一個網頁是一間正在佈置的房間,那麼 display 就是每件家具的「擺放方式」。block 是一張佔滿整面牆的大書櫃(獨佔一行);inline 是牆上並排掛著的小相框(隨文字流一個接一個);flex 是一排可以自動對齊、伸縮的層架(彈性容器);grid 是像圍棋盤那樣的格狀收納櫃(二維網格);hidden 則是直接把家具搬出房間(不佔空間)。而 overflow 決定抽屜塞不下時是關起來看不見還是加個滑軌拉出來,object-fit 決定一張照片怎麼裱進固定尺寸的相框。Tailwind 把整套「佈置規則」標準化,你不再需要每次都手寫 CSS,而是像挑選現成的擺法一樣組合它們。
本篇你將學到:
- display 工具類:
block/inline/inline-block/flex/grid/hidden/contents/flow-root各代表什麼渲染模式,以及響應式切換的寫法 - 溢出與比例:
overflow-*溢出處理、overscroll-*滾動鏈控制、aspect-*長寬比,以及它們如何一起避免版面跳動(CLS) - 圖片與多欄:
object-fit/object-position圖片填充、columns-*瀑布流多欄排版 - 盒模型與其他:
box-sizing、isolation、float/clear,以及 v4 新增的邏輯屬性float-start/float-end
本系列以 TailwindCSS v4 為預設版本,本篇會明確標註每一項與 v3 的差異。
核心概念
版面工具類全景:六大分類對照表
版面相關的工具數量不少,但只要按「它對應哪個 CSS 屬性」來分類,就會發現非常有條理。下面這張表把最核心的六類並列出來,先建立全景地圖:
| 分類 | CSS 屬性 | 代表工具類 | 用途 |
|---|---|---|---|
| 顯示模式 | display | block、flex、grid、hidden、contents | 決定元素的渲染/排列方式 |
| 長寬比 | aspect-ratio | aspect-square、aspect-video、aspect-[4/3] | 鎖定容器比例,避免版面跳動 |
| 溢出處理 | overflow / overscroll-behavior | overflow-hidden、overflow-auto、overscroll-contain | 內容溢出時裁切、捲動或控制滾動鏈 |
| 物件填充 | object-fit / object-position | object-cover、object-contain、object-center | 圖片/影片如何填滿容器 |
| 多欄與斷點 | columns / break-* | columns-3、break-inside-avoid | 瀑布流多欄、控制欄間斷裂 |
| 盒模型與其他 | box-sizing / isolation / float | box-border、isolate、float-left | 尺寸計算基準、堆疊隔離、浮動 |
這張表最需要先建立的認知是:display 是版面的地基,其他工具都建在它之上。你得先決定一個容器是 flex 還是 grid,才有後續 justify-*、grid-cols-* 這些排列工具可用;你得先讓一個元素 block,w-* 高寬設定才有完整意義。所以寫版面的第一個動作,幾乎總是「先想清楚這個盒子的 display 模式」。
理解了這張分類表,接下來寫版面就有一套穩定的思考順序:先決定顯示模式(這個容器用哪套排版規則)、再處理尺寸與比例(它多大、比例鎖不鎖)、接著考慮溢出(內容太多怎麼辦)、最後才是圖片填充、多欄、浮動這些細節。這個從「骨架到細節」的順序,正好對應排版師傅先搭結構、再填內容的直覺流程。而 Tailwind 的價值在於:每一步的決策都對應到一個清楚命名的 class,你不必記 overflow-x: auto; overflow-y: hidden 這種組合,只要 overflow-x-auto overflow-y-hidden 就好。
display 模式:block、inline、flex、grid 的本質差異
display 是這一切的核心,值得先把幾個最常用的模式講清楚。它們的差異,本質上是「這個盒子如何佔位、以及它的子元素用哪套規則排列」:
| Tailwind class | CSS display | 佔位方式 | 典型用途 |
|---|---|---|---|
block | block | 獨佔整行,可設寬高 | div、段落、區塊容器 |
inline | inline | 隨文字流,無法設寬高 | 句子中的 span、連結 |
inline-block | inline-block | 隨文字流,但可設寬高 | 並排的小標籤、按鈕 |
flex | flex | 塊級容器,子元素橫/縱向彈性排列 | 導覽列、卡片列、置中 |
inline-flex | inline-flex | 行內版 flex 容器 | 帶圖示的行內按鈕 |
grid | grid | 塊級容器,子元素依二維網格排列 | 相簿、儀表板、複雜版面 |
hidden | none | 完全移除,不佔空間 | 響應式隱藏、切換內容 |
contents | contents | 移除自身盒子,子元素上升參與祖層排版 | 保留語義標籤又不破壞 Flex/Grid |
flow-root | flow-root | 建立新的區塊格式化上下文(BFC) | 包住浮動元素(現代 clearfix) |
這裡有三個關鍵術語值得記住。第一是 block 與 inline 的根本差異:block 元素像積木一樣由上而下堆疊、各自獨佔一行、可以設定寬高與上下 margin;inline 元素則像文字一樣從左到右流動、不換行、設定寬高無效。inline-block 是折衷——它像 inline 一樣不換行並排,卻又像 block 一樣可以設寬高,很適合做並排的小標籤。
第二是 flex 與 grid 都是「容器」宣告:對元素本身寫 flex 或 grid,改變的不是它自己怎麼排,而是它的直接子元素要用哪套排版引擎。flex 是一維(一條軸線,橫或縱),grid 是二維(行與列同時控制)。這兩個是接下來兩篇的主角,本篇先建立「它們是 display 的一種模式」這個定位。
第三是 contents 與 flow-root 這兩個進階但實用的模式。contents 會讓元素自身的盒子「消失」,把子元素直接提升到祖層去參與排版——這在你有一個語義上必要的包裝標籤(如 <header>),卻不想讓它破壞外層 Flex/Grid 的扁平結構時非常有用。flow-root 則會建立一個全新的 BFC(Block Formatting Context),最經典的用途是包住內部的浮動元素,取代過去那段又臭又長的 clearfix hack。
v4 的版面相關差異
v4 在版面工具上有幾處值得標註的變化,這是本篇要特別點出的:
overflow-clip正式成為 utility:在 v3,若要用overflow: clip得寫任意值overflow-[clip];v4 把它正式收編為overflow-clip。它和overflow-hidden都會裁切溢出內容,但關鍵差異是overflow-clip不會建立新的 BFC、也不會建立滾動容器,因此不影響子層的sticky定位——這是很實用的精準工具。float-start/float-end(v4 新增):對應 CSS 邏輯屬性float: inline-start/inline-end,會依文字方向自動對應左右,天然支援 RTL(由右到左)語系。v3 只有float-left/float-right這種實體方向。- Container Queries 內建:v4 原生支援
@container容器查詢,不再需要額外安裝 plugin。這讓元件可以根據「自身容器寬度」而非「視口寬度」來調整版面,對可重複使用的卡片元件特別有用(屬進階主題,本系列後續會深入)。 aspect-*讀取主題變數:v4 的aspect-video實際上讀取--aspect-ratio-video這個 CSS 變數,延續 v4「CSS-first」的設計方向,你也能在@theme裡自訂比例 Token。
補充一個常被忽略的細節:box-sizing(盒模型)在 Tailwind 的 Preflight 基礎樣式裡預設就把所有元素設為 border-box,也就是說 padding 與 border 會被算進你設定的寬高之內,這通常正是你想要的。box-border 與 box-content 這兩個工具是用來在特定元素上覆蓋這個預設,多數時候你根本不需要動它——知道「預設是 border-box」這件事,本身就能省下很多對不上寬度的困惑。
實作範例
理論看完,我們用幾個可執行的範例把工具串起來。以下都是完整的 HTML + Tailwind,可直接貼進頁面觀察效果。
範例一:響應式顯示與隱藏(導覽列)
最能展現 display 工具威力的場景,就是響應式導覽列——手機顯示漢堡按鈕、桌面顯示完整選單。關鍵就是 hidden 與 md:flex/md:hidden 的搭配:
<!-- 導覽列:手機顯示漢堡選單,桌面顯示完整選單 -->
<nav class="flex items-center justify-between p-4">
<a href="/" class="text-xl font-bold text-gray-900">Logo</a>
<!-- 漢堡按鈕:只有手機版(md 以下)顯示 -->
<button class="block md:hidden p-2">
<span class="block w-6 h-0.5 bg-gray-900 mb-1"></span>
<span class="block w-6 h-0.5 bg-gray-900 mb-1"></span>
<span class="block w-6 h-0.5 bg-gray-900"></span>
</button>
<!-- 完整選單:md 以上才顯示,且是 flex 排列 -->
<ul class="hidden md:flex gap-8 text-sm font-medium">
<li><a href="/about" class="hover:text-cyan-600">關於</a></li>
<li><a href="/work" class="hover:text-cyan-600">作品</a></li>
<li><a href="/contact" class="hover:text-cyan-600">聯絡</a></li>
</ul>
</nav>
這個範例的重點在於用 CSS 而非 JavaScript 管理顯示邏輯。漢堡按鈕寫 block md:hidden——預設(手機)是 block 顯示,到了 md 斷點以上切成 hidden 隱藏;完整選單則相反,寫 hidden md:flex——預設隱藏,md 以上才變成 flex 顯示。兩者一開一關,靠斷點自動切換,不需要任何 JS。特別留意選單那行的 md:flex:它同時做了兩件事——顯示元素、並讓它成為 flex 容器讓內部項目橫向排列,這是 display 工具「切換模式」的典型用法。
範例二:固定比例圖片容器(aspect + object-fit + overflow)
第二個高頻場景是「固定比例的圖片框」——縮圖、頭像、影片封面都需要它,而且要能避免版面跳動。這裡示範 aspect-*、object-*、overflow-hidden 的黃金組合:
<!-- 16:9 影片封面:鎖定比例,圖片填滿並裁切 -->
<div class="aspect-video w-full overflow-hidden rounded-xl bg-gray-100">
<img
src="/cover.jpg"
alt="影片封面"
class="w-full h-full object-cover object-center"
>
</div>
<!-- 正方形頭像:固定尺寸 + 圓形裁切 -->
<div class="w-16 h-16 rounded-full overflow-hidden border-2 border-white shadow-md">
<img src="/avatar.jpg" alt="使用者頭像" class="w-full h-full object-cover">
</div>
<!-- 商品圖:保持完整比例不裁切(object-contain) -->
<div class="aspect-square bg-gray-50 flex items-center justify-center rounded-lg">
<img src="/product.png" alt="商品" class="max-h-full max-w-full object-contain">
</div>
<!-- 直接把 iframe 鎖成 16:9,避免載入時版面抖動 -->
<iframe class="aspect-video w-full rounded-xl" src="https://www.youtube.com/embed/xxxx"></iframe>
這裡有兩個關鍵決策。第一是 aspect-video 先幫容器鎖定 16:9 比例,讓瀏覽器在圖片載入前就預留好正確空間,避免載入完才撐開版面造成 CLS(版面位移)。第二是 object-cover 與 object-contain 的選擇:object-cover 讓圖片填滿容器並裁掉多餘部分(適合封面、頭像,寧可裁切也要填滿),object-contain 則讓圖片完整顯示不裁切、可能留白(適合商品圖、Logo,寧可留白也要看到全貌)。而容器的 overflow-hidden 搭配 rounded-* 圓角是必須的,否則圖片的直角會露在圓角之外。
範例三:可滾動容器與滾動鏈控制(overflow + overscroll)
當內容超過固定高度時,用 overflow-y-auto 做出可滾動區塊;而 overscroll-contain 則能防止滾動穿透到父層:
<!-- 固定高度的可滾動列表 -->
<div class="h-64 overflow-y-auto overscroll-contain border border-gray-200 rounded-lg">
<ul class="divide-y divide-gray-100">
<li class="px-4 py-3 hover:bg-gray-50">項目 1</li>
<li class="px-4 py-3 hover:bg-gray-50">項目 2</li>
<li class="px-4 py-3 hover:bg-gray-50">項目 3</li>
<!-- 更多項目... -->
</ul>
</div>
<!-- 水平滾動的程式碼區塊:長行不換行、改用捲軸 -->
<pre class="overflow-x-auto bg-gray-900 text-gray-100 p-4 rounded-lg text-sm">
<code>const veryLongLine = "Lorem ipsum dolor sit amet consectetur adipiscing elit";</code>
</pre>
overflow-y-auto 的意思是「垂直方向內容溢出時才出現捲軸,沒溢出就不顯示」,比 overflow-y-scroll(永遠顯示捲軸)更乾淨。而 overscroll-contain 是很多人不知道的救星:當你在一個內部可滾動的彈窗或側欄裡滑到底時,預設瀏覽器會把捲動「傳遞」給背後的頁面(叫做 scroll chaining),造成整個頁面跟著動;加上 overscroll-contain 就能把捲動鎖在這個容器內,滑到底就停。這在做 Modal、下拉選單、聊天視窗時特別重要。
範例四:瀑布流多欄(columns)與盒模型隔離(isolation)
最後示範 columns-* 做瀑布流版面,以及 isolate 建立獨立的堆疊上下文:
<!-- 瀑布流卡片:不同高度的卡片自動填入最短的欄 -->
<div class="columns-1 sm:columns-2 lg:columns-3 gap-6">
<div class="break-inside-avoid mb-6 bg-white rounded-xl shadow-sm p-6">
<img src="/pic1.jpg" class="w-full rounded-lg mb-4" alt="圖片一">
<p class="text-gray-700">短卡片內容。</p>
</div>
<div class="break-inside-avoid mb-6 bg-white rounded-xl shadow-sm p-6">
<p class="text-gray-700">較長的卡片內容段落,高度不同的卡片會自動填充到最短的欄,形成瀑布流效果。</p>
<p class="text-gray-500 text-sm mt-4">副標記</p>
</div>
<!-- 更多卡片... -->
</div>
<!-- isolate:建立獨立堆疊上下文,讓內部的 z-index 不外洩 -->
<div class="isolate relative">
<div class="absolute inset-0 z-10 bg-cyan-500/20"></div>
<p class="relative z-20">這裡的 z-index 只在這個 isolate 容器內比較</p>
</div>
columns-3 會把內容切成三欄由上而下、由左而右流動,天生就是瀑布流版面(不需要 Grid 或 JS 計算高度)。但有一個必配的工具:break-inside-avoid,它防止一張卡片在欄與欄的交界處被硬生生切成兩半。忘了加這個,你會看到卡片上半截在左欄、下半截在右欄的災難畫面。
isolate(對應 isolation: isolate)則是處理堆疊順序的利器:它會建立一個新的堆疊上下文(stacking context),讓容器內部的 z-index 自成一個小世界、不會和外部的 z-index 互相干擾。當你的頁面有很多層 overlay、又不想讓某個元件的 z-50 意外蓋過或被蓋過其他區塊時,在它外層加 isolate 就能把它的 z-index 戰場隔離開來。
常見錯誤與最佳實踐
四個最容易踩的版面坑
坑一:用 invisible 卻以為元素會消失。 invisible(visibility: hidden)雖然看不見,但仍佔著原本的空間,後面的元素不會補上來。想讓元素徹底消失、不佔空間,要用 hidden(display: none):
<div class="invisible">這個看不見,但還佔著空間!</div> <!-- ❌ 多數情況不是你要的 -->
<div class="hidden">這個徹底消失,不佔空間</div> <!-- ✅ 響應式隱藏的正解 -->
坑二:父層 overflow-hidden 讓子層 sticky 失效。 sticky 相對於「最近的可滾動祖先」定位,而任何 overflow-hidden/auto/scroll 的祖先都會成為滾動容器並干擾它。若那個 overflow 只是為了裁切裝飾,改用 v4 的 overflow-clip(裁切但不建立滾動容器、不影響 sticky):
<!-- ❌ 父層 overflow-hidden 讓內部 sticky 側欄失效 -->
<div class="overflow-hidden">
<aside class="sticky top-4">側欄</aside>
</div>
<!-- ✅ 只需裁切裝飾時改用 overflow-clip,sticky 正常運作 -->
<div class="overflow-clip">
<aside class="sticky top-4">側欄</aside>
</div>
坑三:columns 多欄忘了加 break-inside-avoid。 沒加這個,卡片會在欄交界被切成兩半。凡是放進 columns-* 的子項目,幾乎都該加上它:
<div class="columns-3">
<div>...</div> <!-- ❌ 卡片可能被切斷 -->
<div class="break-inside-avoid">...</div> <!-- ✅ 卡片保持完整 -->
</div>
坑四:在 <button>、<a> 上用 contents 造成無障礙問題。 display: contents 會移除元素的盒子與其語義角色,在互動元素(<button>、<a>、<summary>)上使用,會讓輔助科技無法正確辨識這些元素,破壞鍵盤與螢幕閱讀器操作。contents 應該只用在純結構性的包裝 <div>/<section> 上:
<button class="contents">送出</button> <!-- ❌ 破壞按鈕語義與無障礙 -->
<div class="contents">...</div> <!-- ✅ 只在無語義的包裝層使用 -->
版面最佳實踐清單
- 響應式顯示用
hidden+ 斷點前綴,不要用 JS:hidden md:block、block md:hidden讓 CSS 接管顯示邏輯,更快、無閃爍。 - 圖片框用
aspect-*鎖比例避免 CLS:容器先鎖定比例,瀏覽器就能預留空間,改善 Core Web Vitals。 - 填滿用
object-cover、完整顯示用object-contain:封面/頭像寧可裁切要 cover,商品/Logo 要看全貌用 contain。 - 只需裁切且要保留
sticky時用overflow-clip:v4 新工具,比overflow-hidden更精準、不建立滾動容器。 - 可滾動容器加
overscroll-contain:Modal、側欄、聊天視窗防止滾動穿透到背景頁面。 columns-*的子項一律加break-inside-avoid:防止卡片跨欄被切斷。
小結
這是 TailwindCSS 完整教學 系列的第八篇,也是 TW-3 版面與定位章節的開場。上一篇《排版與文字》我們把 font-*、text-*、leading-* 這些文字層的工具講透,讓字排得好看又好讀;這一篇則從文字往外走一層,進入版面的骨架——用 display 決定元素怎麼排列、用 overflow 處理溢出、用 object-fit 填充圖片。回顧幾個重點:
- display 是地基:
block/inline/flex/grid/hidden/contents/flow-root各代表一種渲染模式,先決定 display,後續版面工具才有意義。 - 固定比例圖片框:
aspect-*鎖比例 +object-cover/contain填充 +overflow-hidden裁切,是縮圖與頭像的黃金組合,還能避免 CLS。 - 溢出與滾動鏈:
overflow-auto/hidden/clip處理溢出,overscroll-contain防止滾動穿透,v4 的overflow-clip不影響 sticky。 - 多欄與其他:
columns-*做瀑布流(記得配break-inside-avoid)、isolate隔離 z-index、box-border(v4 預設)掌管盒模型、float-start/end是 v4 的 RTL 友善新工具。 - 最容易踩的坑:
hidden與invisible別搞混、父層 overflow 會讓 sticky 失效、互動元素別用contents。
版面工具就像蓋房子的鋼骨——先立好骨架,後面的排列、對齊、間距才有地方掛。下一篇 《TailwindCSS Flexbox 完整指南》,我們會深入 flex 這個最常用的一維版面引擎,把 justify-*、items-*、flex-1、gap-* 這些工具一次講清楚,看 Tailwind 如何用一組 utility 就搞定置中、等分、換行這些每天都在寫的版面需求。