
本篇將深入探討現代 CSS 布局技術,從傳統的 Float 開始,重點介紹目前主流的 FlexBox 和 CSS Grid 技術。您將學會如何選擇適合的布局方法,掌握一維和二維布局的核心概念,並能夠設計出現代化的響應式網頁布局。
重要提醒
本文將說明 Float 的基本概念,但在現代網頁開發中,強烈建議使用 FlexBox 和 Grid 進行布局設計。Float 主要用於文繞圖效果,而非頁面布局。
浮動 Float - 傳統技術
Float 最初是為了實現文繞圖效果而設計的 CSS 屬性。雖然過去常用於布局,但現在主要用途僅限於文繞圖。
核心特性
Float 會讓元素產生浮動行為,脫離正常的文件流,並緊貼到指定的方向。
- 浮動元素會變成 block 性質
- 其他元素會環繞浮動元素(文繞圖效果)
- 父容器可能會失去高度(高度塌陷)
index.html<style> .container { width: 400px; margin: 0 auto; border: 2px solid #333; padding: 20px; }
.float-image { float: right; margin: 0 0 10px 10px; border-radius: 8px; }
.text-content { text-align: justify; line-height: 1.6; } </style>
<div class="container"> <h2>文繞圖範例</h2> <img src="https://picsum.photos/150/150/?random=1" alt="示例圖片" class="float-image"> <div class="text-content"> <p>這是一段示例文字,用來展示文繞圖的效果。當圖片設定為 float: right 時,文字會自動環繞在圖片周圍,形成美觀的排版效果。</p> <p>這種技術在文章排版、部落格文章或新聞網站中非常常見,能夠有效利用空間並提升視覺效果。</p> </div>
|
高度塌陷問題與解決方案
當所有子元素都浮動時,父容器會失去高度。
素材準備:觀察高度塌陷現象
以下範例展示了高度塌陷問題及其解決方案。
float-collapse.html<style> .container { width: 600px; margin: 20px auto; border: 3px solid #e74c3c; background: #f8f9fa; }
.float-item { float: left; width: 180px; height: 120px; margin: 10px; background: #3498db; color: white; text-align: center; line-height: 120px; border-radius: 8px; }
.clearfix::after { content: ""; display: table; clear: both; } </style>
<div class="container"> <div class="float-item">項目 1</div> <div class="float-item">項目 2</div> <div class="float-item">項目 3</div> </div>
<div class="container clearfix"> <div class="float-item">項目 1</div> <div class="float-item">項目 2</div> <div class="float-item">項目 3</div> </div>
|
Float 布局的問題
- 高度塌陷需要額外處理
- 響應式設計困難
- 代碼複雜且難以維護
- 現代開發不建議用於布局
舊技術 - 使用 float 排版
這是早期使用 float 技術完成 1024x768 的版面 container 切版的範例,他沒有良好的響應式功能,包含以下四個區塊 header、left、right、footer。
.container{ font-family: "Microsoft JhengHei"; width: 1024px; height: 768px; border: 1px solid #000; color: white; font-size: 3rem; text-align: center; }
.header { width: 1024px; height: 100px; background: #000; } .left { width: 200px; height: 568px; background: #aaa; float: left; } .right { width: 824px; height: 568px; background: #777; float: right; } .footer { width: 1024px; height: 100px; background: #000; clear: both; }
|
<div class="container"> <div class="header">Header</div> <div class="left">Left</div> <div class="right">Right</div> <div class="footer">Footer</div> </div>
|
彈性盒子 FlexBox
FlexBox(彈性盒子)是 CSS3 推出的革命性布局技術,專門用於一維布局(水平或垂直方向)。它不僅能輕鬆解決傳統布局的痛點,更帶來了全新的思維模式和強大的彈性特性。
為什麼要使用 FlexBox?
在深入學習 FlexBox 之前,讓我們先了解它為什麼如此重要。FlexBox 的出現徹底改變了 CSS 布局的遊戲規則,解決了多年來困擾開發者的布局難題。
傳統布局的痛點
在 FlexBox 出現之前,CSS 布局存在許多挑戰:
- 垂直居中困難:需要複雜的技巧才能實現簡單的垂直居中
- 等高布局複雜:實現等高欄位需要許多 hack 技巧
- 空間分配不靈活:無法簡單地讓元素自動分配剩餘空間
- 響應式設計困難:需要大量的媒體查詢和複雜的計算
FlexBox 的革命性優勢
FlexBox 的核心價值
- 彈性:項目可以自動伸縮以適應容器大小
- 對齊:提供強大的對齊控制能力
- 順序:可以改變項目的顯示順序而不修改 HTML
- 響應式:天生適合響應式設計
flexbox-advantage.html<style> .traditional-layout { width: 100%; background: #f8f9fa; padding: 20px; margin-bottom: 20px; }
.traditional-layout .item { float: left; width: 33.333%; box-sizing: border-box; padding: 10px; background: #dc3545; color: white; text-align: center; }
.traditional-layout::after { content: ""; display: table; clear: both; }
.flex-layout { display: flex; gap: 20px; background: #f8f9fa; padding: 20px; }
.flex-layout .item { flex: 1; padding: 10px; background: #28a745; color: white; text-align: center; } </style>
<div class="traditional-layout"> <div class="item">項目 1</div> <div class="item">項目 2</div> <div class="item">項目 3</div> </div>
<div class="flex-layout"> <div class="item">項目 1</div> <div class="item">項目 2</div> <div class="item">項目 3</div> </div>
|
盒子模型的變化與核心概念
當我們設定 display: flex
時,不僅改變了容器的行為,更重要的是對所有子元素產生了根本性的影響。理解這些變化是掌握 FlexBox 的關鍵基礎。
FlexBox 對子元素的影響
當容器設定 display: flex
時,所有直接子元素都會發生根本性的變化:
重要變化
- 行內元素自動變成塊級行為:
span
、a
等行內元素會具有類似 block
的特性
- 可設定寬高:原本不能設定寬高的行內元素現在可以設定
- 垂直對齊改變:
vertical-align
屬性失效,改用 align-items
和 align-self
- 浮動失效:
float
和 clear
屬性對 flex 項目無效
- 絕對定位影響:
position: absolute
會讓元素脫離 flex 流
box-model-change.html<style> .demo-container { margin: 20px 0; padding: 20px; border: 2px solid #dee2e6; }
.normal-container { background: #f8f9fa; }
.flex-container { display: flex; gap: 10px; background: #e9ecef; }
.inline-item { background: #007bff; color: white; padding: 10px; margin: 5px; border-radius: 4px; }
.flex-container .inline-item { width: 100px; height: 50px; display: flex; align-items: center; justify-content: center; } </style>
<h4>一般容器中的行內元素</h4> <div class="demo-container normal-container"> <span class="inline-item">Span 1</span> <a href="#" class="inline-item">Link 2</a> <em class="inline-item">Em 3</em> </div>
<h4>Flex 容器中的行內元素</h4> <div class="demo-container flex-container"> <span class="inline-item">Span 1</span> <a href="#" class="inline-item">Link 2</a> <em class="inline-item">Em 3</em> </div>
|
主軸與交叉軸的深入理解
FlexBox 的核心在於「軸」的概念,這決定了所有布局行為。理解軸的運作方式是掌握 FlexBox 的關鍵。

軸的基本概念
- 主軸(Main Axis):Flex 項目的主要排列方向
- 交叉軸(Cross Axis):與主軸垂直的方向
- 主軸起點(Main Start):主軸的開始位置
- 主軸終點(Main End):主軸的結束位置
- 交叉軸起點(Cross Start):交叉軸的開始位置
- 交叉軸終點(Cross End):交叉軸的結束位置
axis-concept.html<style> .axis-demo { display: flex; height: 200px; background: #f8f9fa; margin: 20px 0; border: 2px solid #007bff; position: relative; }
.axis-demo::before { content: attr(data-direction); position: absolute; top: -30px; left: 0; font-weight: bold; color: #007bff; }
.axis-item { background: #28a745; color: white; padding: 20px; margin: 10px; border-radius: 5px; text-align: center; min-width: 80px; }
.row-demo { flex-direction: row; }
.column-demo { flex-direction: column; }
.row-reverse-demo { flex-direction: row-reverse; }
.column-reverse-demo { flex-direction: column-reverse; } </style>
<div class="axis-demo row-demo" data-direction="flex-direction: row(預設)"> <div class="axis-item">1</div> <div class="axis-item">2</div> <div class="axis-item">3</div> </div>
<div class="axis-demo column-demo" data-direction="flex-direction: column"> <div class="axis-item">1</div> <div class="axis-item">2</div> <div class="axis-item">3</div> </div>
<div class="axis-demo row-reverse-demo" data-direction="flex-direction: row-reverse"> <div class="axis-item">1</div> <div class="axis-item">2</div> <div class="axis-item">3</div> </div>
<div class="axis-demo column-reverse-demo" data-direction="flex-direction: column-reverse"> <div class="axis-item">1</div> <div class="axis-item">2</div> <div class="axis-item">3</div> </div>
|
父容器屬性完整指南
FlexBox 的父容器提供了 8 個核心屬性,每個都有其特定的用途和效果。掌握這些屬性是運用 FlexBox 的關鍵所在。
1. display 屬性
設定元素為 flex 容器,啟用 FlexBox 布局系統。
預設值:block、inline 等
元素預設不是 flex 容器,需要明確設定 display: flex
或 display: inline-flex
才能啟用 FlexBox。
.container { display: flex; display: inline-flex; }
|
2. flex-direction 屬性
控制主軸的方向,決定 flex 項目的排列方向:
flex-direction-demo.html<style> .direction-container { display: flex; height: 150px; background: #e9ecef; margin: 15px 0; border: 2px solid #495057; padding: 10px; }
.direction-item { background: #007bff; color: white; padding: 15px; margin: 5px; border-radius: 4px; text-align: center; min-width: 60px; }
.row { flex-direction: row; } .row-reverse { flex-direction: row-reverse; } .column { flex-direction: column; } .column-reverse { flex-direction: column-reverse; } </style>
<h4>flex-direction: row(預設)</h4> <div class="direction-container row"> <div class="direction-item">1</div> <div class="direction-item">2</div> <div class="direction-item">3</div> </div>
<h4>flex-direction: row-reverse</h4> <div class="direction-container row-reverse"> <div class="direction-item">1</div> <div class="direction-item">2</div> <div class="direction-item">3</div> </div>
<h4>flex-direction: column</h4> <div class="direction-container column"> <div class="direction-item">1</div> <div class="direction-item">2</div> <div class="direction-item">3</div> </div>
<h4>flex-direction: column-reverse</h4> <div class="direction-container column-reverse"> <div class="direction-item">1</div> <div class="direction-item">2</div> <div class="direction-item">3</div> </div>
|
3. flex-wrap 屬性
控制 flex 項目是否換行:
預設值:nowrap
項目預設不換行,會在一行內壓縮以適應容器寬度。
flex-wrap-demo.html<style> .wrap-container { display: flex; width: 400px; background: #f8f9fa; border: 2px solid #6c757d; padding: 10px; margin: 15px 0; }
.wrap-item { background: #28a745; color: white; padding: 15px; margin: 5px; border-radius: 4px; text-align: center; width: 120px; }
.nowrap { flex-wrap: nowrap; } .wrap { flex-wrap: wrap; } .wrap-reverse { flex-wrap: wrap-reverse; } </style>
<h4>flex-wrap: nowrap(預設)</h4> <div class="wrap-container nowrap"> <div class="wrap-item">項目 1</div> <div class="wrap-item">項目 2</div> <div class="wrap-item">項目 3</div> <div class="wrap-item">項目 4</div> </div>
<h4>flex-wrap: wrap</h4> <div class="wrap-container wrap"> <div class="wrap-item">項目 1</div> <div class="wrap-item">項目 2</div> <div class="wrap-item">項目 3</div> <div class="wrap-item">項目 4</div> </div>
<h4>flex-wrap: wrap-reverse</h4> <div class="wrap-container wrap-reverse"> <div class="wrap-item">項目 1</div> <div class="wrap-item">項目 2</div> <div class="wrap-item">項目 3</div> <div class="wrap-item">項目 4</div> </div>
|
4. flex-flow 屬性
flex-flow
是 flex-direction
和 flex-wrap
的簡寫:
預設值:row nowrap
等同於 flex-direction: row
和 flex-wrap: nowrap
。
.container { flex-flow: row wrap; flex-flow: column nowrap; flex-flow: row-reverse wrap; }
|
5. justify-content 屬性
控制項目在主軸上的對齊方式:
預設值:flex-start
項目預設對齊到主軸的起始位置(通常是左邊)。
justify-content-demo.html<style> .justify-container { display: flex; height: 100px; background: #e3f2fd; margin: 15px 0; border: 2px solid #2196f3; padding: 10px; }
.justify-item { background: #2196f3; color: white; padding: 15px; margin: 5px; border-radius: 4px; text-align: center; width: 80px; }
.flex-start { justify-content: flex-start; } .flex-end { justify-content: flex-end; } .center { justify-content: center; } .space-between { justify-content: space-between; } .space-around { justify-content: space-around; } .space-evenly { justify-content: space-evenly; } </style>
<h4>justify-content: flex-start(預設)</h4> <div class="justify-container flex-start"> <div class="justify-item">A</div> <div class="justify-item">B</div> <div class="justify-item">C</div> </div>
<h4>justify-content: flex-end</h4> <div class="justify-container flex-end"> <div class="justify-item">A</div> <div class="justify-item">B</div> <div class="justify-item">C</div> </div>
<h4>justify-content: center</h4> <div class="justify-container center"> <div class="justify-item">A</div> <div class="justify-item">B</div> <div class="justify-item">C</div> </div>
<h4>justify-content: space-between</h4> <div class="justify-container space-between"> <div class="justify-item">A</div> <div class="justify-item">B</div> <div class="justify-item">C</div> </div>
<h4>justify-content: space-around</h4> <div class="justify-container space-around"> <div class="justify-item">A</div> <div class="justify-item">B</div> <div class="justify-item">C</div> </div>
<h4>justify-content: space-evenly</h4> <div class="justify-container space-evenly"> <div class="justify-item">A</div> <div class="justify-item">B</div> <div class="justify-item">C</div> </div>
|
6. align-items 屬性
控制項目在交叉軸上的對齊方式:
預設值:stretch
項目預設會拉伸以填滿交叉軸方向的空間。
align-items-demo.html<style> .align-items-container { display: flex; height: 150px; background: #f3e5f5; margin: 15px 0; border: 2px solid #9c27b0; padding: 10px; }
.align-items-item { background: #9c27b0; color: white; padding: 15px; margin: 5px; border-radius: 4px; text-align: center; width: 80px; }
.align-items-item:nth-child(2) { height: 80px; }
.align-items-item:nth-child(3) { height: 120px; }
.stretch { align-items: stretch; } .flex-start { align-items: flex-start; } .flex-end { align-items: flex-end; } .center { align-items: center; } .baseline { align-items: baseline; } </style>
<h4>align-items: stretch(預設)</h4> <div class="align-items-container stretch"> <div class="align-items-item">A</div> <div class="align-items-item">B</div> <div class="align-items-item">C</div> </div>
<h4>align-items: flex-start</h4> <div class="align-items-container flex-start"> <div class="align-items-item">A</div> <div class="align-items-item">B</div> <div class="align-items-item">C</div> </div>
<h4>align-items: flex-end</h4> <div class="align-items-container flex-end"> <div class="align-items-item">A</div> <div class="align-items-item">B</div> <div class="align-items-item">C</div> </div>
<h4>align-items: center</h4> <div class="align-items-container center"> <div class="align-items-item">A</div> <div class="align-items-item">B</div> <div class="align-items-item">C</div> </div>
<h4>align-items: baseline</h4> <div class="align-items-container baseline"> <div class="align-items-item">A</div> <div class="align-items-item">B</div> <div class="align-items-item">C</div> </div>
|
7. align-content 屬性
控制多行項目在交叉軸上的對齊方式(只在多行時有效):
預設值:stretch
多行項目預設會拉伸以填滿交叉軸方向的空間。
align-content-demo.html<style> .align-content-container { display: flex; flex-wrap: wrap; width: 300px; height: 200px; background: #e8f5e8; margin: 15px 0; border: 2px solid #4caf50; padding: 10px; }
.align-content-item { background: #4caf50; color: white; padding: 15px; margin: 5px; border-radius: 4px; text-align: center; width: 80px; }
.stretch { align-content: stretch; } .flex-start { align-content: flex-start; } .flex-end { align-content: flex-end; } .center { align-content: center; } .space-between { align-content: space-between; } .space-around { align-content: space-around; } </style>
<h4>align-content: stretch(預設)</h4> <div class="align-content-container stretch"> <div class="align-content-item">1</div> <div class="align-content-item">2</div> <div class="align-content-item">3</div> <div class="align-content-item">4</div> <div class="align-content-item">5</div> </div>
<h4>align-content: flex-start</h4> <div class="align-content-container flex-start"> <div class="align-content-item">1</div> <div class="align-content-item">2</div> <div class="align-content-item">3</div> <div class="align-content-item">4</div> <div class="align-content-item">5</div> </div>
<h4>align-content: center</h4> <div class="align-content-container center"> <div class="align-content-item">1</div> <div class="align-content-item">2</div> <div class="align-content-item">3</div> <div class="align-content-item">4</div> <div class="align-content-item">5</div> </div>
<h4>align-content: space-between</h4> <div class="align-content-container space-between"> <div class="align-content-item">1</div> <div class="align-content-item">2</div> <div class="align-content-item">3</div> <div class="align-content-item">4</div> <div class="align-content-item">5</div> </div>
|
8. gap 屬性
是 FlexBox 與 Grid 佈局中用來「控制子項目之間間距」的複合屬性。它同時代表了 row-gap
(行間距)與 column-gap
(列間距),可以一次設定兩個方向的間距,讓版面更整齊、間距更容易管理。項目之間預設沒有間距預設值:0。
gap-demo.html<style> .gap-container { display: flex; flex-wrap: wrap; background: #fff3e0; margin: 15px 0; border: 2px solid #ff9800; padding: 10px; }
.gap-item { background: #ff9800; color: white; padding: 15px; border-radius: 4px; text-align: center; width: 80px; }
.gap-10 { gap: 10px; } .gap-20 { gap: 20px; } .gap-row-col { gap: 10px 20px; } </style>
<h4>gap: 10px</h4> <div class="gap-container gap-10"> <div class="gap-item">1</div> <div class="gap-item">2</div> <div class="gap-item">3</div> <div class="gap-item">4</div> </div>
<h4>gap: 20px</h4> <div class="gap-container gap-20"> <div class="gap-item">1</div> <div class="gap-item">2</div> <div class="gap-item">3</div> <div class="gap-item">4</div> </div>
<h4>gap: 10px 20px(行間距 列間距)</h4> <div class="gap-container gap-row-col"> <div class="gap-item">1</div> <div class="gap-item">2</div> <div class="gap-item">3</div> <div class="gap-item">4</div> <div class="gap-item">5</div> <div class="gap-item">6</div> </div>
|
子元素屬性完整指南
掌握了父容器的 8 個屬性後,我們需要了解子元素(flex 項目)的屬性。這 6 個屬性讓我們能夠精確控制每個項目的行為,實現更靈活的布局效果。
flex-basis 屬性
flex-basis
是 flex 項目的基礎尺寸,決定了項目在主軸方向上的初始大小。理解它與 width
和 height
的關係是掌握 FlexBox 的關鍵。
預設值:auto
當 flex-basis
為 auto
時,會檢查項目是否有明確的 width
或 height
,如果有就使用該值,沒有則根據內容自動調整。
與 width/height 的優先考量
flex-basis-priority.html<style> .basis-priority-demo { display: flex; background: #f8f9fa; border: 2px solid #6c757d; padding: 20px; margin: 20px 0; gap: 10px; }
.basis-item { background: #007bff; color: white; padding: 15px; border-radius: 4px; text-align: center; font-weight: bold; }
.item-width-only { width: 150px; }
.item-basis-only { flex-basis: 200px; }
.item-both { width: 100px; flex-basis: 250px; } </style>
<div class="basis-priority-demo"> <div class="basis-item item-width-only">寬度 150px</div> <div class="basis-item item-basis-only">flex-basis 200px</div> <div class="basis-item item-both">寬度 100px<br>flex-basis 250px</div> </div>
|
flex-basis 的優先級法則
- 有 flex-basis 時:flex-basis 優先於 width/height
- flex-basis 為 auto:使用 width/height 的值
- 都沒有時:根據內容自動調整
- 主軸方向:水平時影響寬度,垂直時影響高度
flex-basis 的各種值
flex-basis-values.html<style> .basis-values-demo { display: flex; background: #e9ecef; border: 2px solid #495057; padding: 20px; margin: 20px 0; gap: 10px; }
.basis-values-item { background: #6c757d; color: white; padding: 15px; border-radius: 4px; text-align: center; font-weight: bold; }
.basis-auto { flex-basis: auto; width: 120px; }
.basis-0 { flex-basis: 0; width: 120px; }
.basis-content { flex-basis: content; }
.basis-fixed { flex-basis: 200px; }
.basis-percent { flex-basis: 30%; } </style>
<div class="basis-values-demo"> <div class="basis-values-item basis-auto">auto<br>(使用 width)</div> <div class="basis-values-item basis-0">0<br>(忽略 width)</div> <div class="basis-values-item basis-content">content<br>(內容決定)</div> <div class="basis-values-item basis-fixed">200px<br>(固定大小)</div> <div class="basis-values-item basis-percent">30%<br>(百分比)</div> </div>
|
flex-grow 屬性
flex-grow
控制項目如何分配剩餘空間。只有當容器有多餘空間時,這個屬性才會生效。
預設值:0
預設情況下,項目不會伸長來填滿剩餘空間,保持其原有尺寸。
剩餘空間的分配邏輯
flex-grow-logic.html<style> .grow-logic-demo { display: flex; width: 600px; background: #e3f2fd; border: 2px solid #2196f3; padding: 20px; margin: 20px 0; gap: 10px; }
.grow-logic-item { background: #2196f3; color: white; padding: 15px; border-radius: 4px; text-align: center; font-weight: bold; flex-basis: 100px; }
.grow-0 { flex-grow: 0; background: #f44336; } .grow-1 { flex-grow: 1; background: #4caf50; } .grow-2 { flex-grow: 2; background: #ff9800; } .grow-3 { flex-grow: 3; background: #9c27b0; } </style>
<div class="grow-logic-demo"> <div class="grow-logic-item grow-0">flex-grow: 0</div> <div class="grow-logic-item grow-1">flex-grow: 1</div> <div class="grow-logic-item grow-2">flex-grow: 2</div> <div class="grow-logic-item grow-3">flex-grow: 3</div> </div>
|
比例分配的計算方式
grow-calculation.html<style> .calculation-demo { background: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0; }
.demo-container { display: flex; width: 500px; background: #ffffff; border: 3px solid #007bff; padding: 10px; margin: 15px auto; gap: 10px; }
.demo-item { background: #28a745; color: white; padding: 10px; border-radius: 4px; text-align: center; font-weight: bold; flex-basis: 80px; transition: all 0.3s ease; }
.demo-1 .demo-item:nth-child(1) { flex-grow: 1; } .demo-1 .demo-item:nth-child(2) { flex-grow: 2; } .demo-1 .demo-item:nth-child(3) { flex-grow: 3; }
.demo-2 .demo-item:nth-child(1) { flex-grow: 2; } .demo-2 .demo-item:nth-child(2) { flex-grow: 2; } .demo-2 .demo-item:nth-child(3) { flex-grow: 2; }
.demo-item:nth-child(1) { background: #dc3545; } .demo-item:nth-child(2) { background: #ffc107; color: #212529; } .demo-item:nth-child(3) { background: #17a2b8; }
.calculation-note { background: #e7f3ff; padding: 15px; border-radius: 6px; margin: 10px 0; font-size: 0.9rem; } </style>
<div class="calculation-demo"> <h5>計算範例:容器寬度 500px,每個項目 flex-basis: 80px</h5> <div class="calculation-note"> <strong>剩餘空間 = 500px - (3 × 80px) - 間距 = 340px</strong> </div>
<div class="demo-container demo-1"> <div class="demo-item">1</div> <div class="demo-item">2</div> <div class="demo-item">3</div> </div> <div class="calculation-note"> <strong>flex-grow 比例 1:2:3</strong><br> • 總比例 = 1 + 2 + 3 = 6<br> • 項目 1 額外獲得:340px × (1/6) = 56.67px<br> • 項目 2 額外獲得:340px × (2/6) = 113.33px<br> • 項目 3 額外獲得:340px × (3/6) = 170px </div>
<div class="demo-container demo-2"> <div class="demo-item">2</div> </div> <div class="calculation-note"> <strong>flex-grow 比例 2:2:2(平均分配)</strong><br> • 總比例 = 2 + 2 + 2 = 6<br> • 每個項目額外獲得:340px × (2/6) = 113.33px </div> </div>
|
flex-shrink 屬性
flex-shrink
控制項目如何收縮以適應空間不足的情況。當容器空間不足時,這個屬性決定哪些項目收縮更多。
預設值:1
預設情況下,所有項目都會等比例收縮以適應容器空間。設為 0 則不收縮。
收縮空間的分配邏輯
flex-shrink-logic.html<style> .shrink-logic-demo { display: flex; width: 300px; background: #ffebee; border: 2px solid #f44336; padding: 20px; margin: 20px 0; gap: 10px; }
.shrink-logic-item { background: #f44336; color: white; padding: 15px; border-radius: 4px; text-align: center; font-weight: bold; flex-basis: 150px; }
.shrink-0 { flex-shrink: 0; background: #4caf50; } .shrink-1 { flex-shrink: 1; background: #ff9800; } .shrink-2 { flex-shrink: 2; background: #9c27b0; } </style>
<div class="shrink-logic-demo"> <div class="shrink-logic-item shrink-0">不收縮</div> <div class="shrink-logic-item shrink-1">收縮 1</div> <div class="shrink-logic-item shrink-2">收縮 2</div> </div>
|
收縮比例的計算方式
shrink-calculation.html<style> .shrink-calculation-demo { background: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0; }
.shrink-demo-container { display: flex; width: 400px; background: #ffffff; border: 3px solid #dc3545; padding: 10px; margin: 15px auto; gap: 10px; }
.shrink-demo-item { background: #dc3545; color: white; padding: 10px; border-radius: 4px; text-align: center; font-weight: bold; flex-basis: 200px; transition: all 0.3s ease; }
.shrink-demo-1 .shrink-demo-item:nth-child(1) { flex-shrink: 1; } .shrink-demo-1 .shrink-demo-item:nth-child(2) { flex-shrink: 2; } .shrink-demo-1 .shrink-demo-item:nth-child(3) { flex-shrink: 3; }
.shrink-demo-item:nth-child(1) { background: #dc3545; } .shrink-demo-item:nth-child(2) { background: #ffc107; color: #212529; } .shrink-demo-item:nth-child(3) { background: #17a2b8; }
.shrink-note { background: #fff5f5; padding: 15px; border-radius: 6px; margin: 10px 0; font-size: 0.9rem; border: 1px solid #fed7d7; } </style>
<div class="shrink-calculation-demo"> <h5>收縮計算範例:容器寬度 400px,每個項目 flex-basis: 200px</h5> <div class="shrink-note"> <strong>需要收縮的空間 = (3 × 200px) - 400px = 200px</strong> </div>
<div class="shrink-demo-container shrink-demo-1"> <div class="shrink-demo-item">1</div> <div class="shrink-demo-item">2</div> <div class="shrink-demo-item">3</div> </div> <div class="shrink-note"> <strong>flex-shrink 比例 1:2:3</strong><br> • 總比例 = 1 + 2 + 3 = 6<br> • 項目 1 收縮:200px × (1/6) = 33.33px → 最終寬度 166.67px<br> • 項目 2 收縮:200px × (2/6) = 66.67px → 最終寬度 133.33px<br> • 項目 3 收縮:200px × (3/6) = 100px → 最終寬度 100px </div> </div>
|
flex 屬性
flex
屬性是 flex-grow
、flex-shrink
和 flex-basis
的簡寫,提供了快速設置的方式。
預設值:0 1 auto
等同於 flex: initial
,表示項目不伸長、可收縮、基礎尺寸為 auto。
常用的 flex 值
flex-shorthand.html<style> .flex-demo { display: flex; background: #f8f9fa; border: 2px solid #6c757d; padding: 20px; margin: 20px 0; gap: 10px; }
.flex-item { background: #007bff; color: white; padding: 15px; border-radius: 4px; text-align: center; font-weight: bold; min-height: 50px; }
.flex-1 { flex: 1; } .flex-auto { flex: auto; } .flex-none { flex: none; } .flex-0 { flex: 0; } .flex-custom { flex: 2 1 200px; } </style>
<div class="flex-demo"> <div class="flex-item flex-1">flex: 1</div> <div class="flex-item flex-auto">flex: auto</div> <div class="flex-item flex-none">flex: none</div> </div>
<div class="flex-demo"> <div class="flex-item flex-0">flex: 0</div> <div class="flex-item flex-custom">flex: 2 1 200px</div> <div class="flex-item flex-1">flex: 1</div> </div>
|
flex 簡寫值說明
flex: 1
= flex: 1 1 0
:平均分配空間,忽略內容大小
flex: auto
= flex: 1 1 auto
:平均分配空間,考慮內容大小
flex: none
= flex: 0 0 auto
:不伸縮,保持內容大小
flex: 0
= flex: 0 1 0
:不伸長但可收縮
flex: initial
= flex: 0 1 auto
:預設值
order 屬性
控制 flex 項目的排列順序,數值越小越靠前:
預設值:0
所有項目的預設 order 值都是 0,按照 HTML 源碼順序排列。
order-demo.html<style> .order-container { display: flex; background: #e1f5fe; margin: 15px 0; border: 2px solid #0288d1; padding: 10px; }
.order-item { background: #0288d1; color: white; padding: 20px; margin: 5px; border-radius: 4px; text-align: center; width: 80px; }
.order-1 { order: 1; } .order-2 { order: 2; } .order-3 { order: 3; } .order-minus-1 { order: -1; } </style>
<h4>預設順序(HTML 順序)</h4> <div class="order-container"> <div class="order-item">第一個</div> <div class="order-item">第二個</div> <div class="order-item">第三個</div> </div>
<h4>使用 order 改變順序</h4> <div class="order-container"> <div class="order-item order-3">order: 3</div> <div class="order-item order-1">order: 1</div> <div class="order-item order-2">order: 2</div> </div>
<h4>負數 order 值</h4> <div class="order-container"> <div class="order-item">預設 (0)</div> <div class="order-item order-minus-1">order: -1</div> <div class="order-item">預設 (0)</div> </div>
|
align-self 屬性
覆寫父容器的 align-items
設定,單獨控制某個項目的交叉軸對齊:
預設值:auto
繼承父容器的 align-items
設定。如果父容器沒有設定,則使用 stretch
。
align-self-demo.html<style> .align-self-container { display: flex; align-items: center; height: 150px; background: #f3e5f5; margin: 15px 0; border: 2px solid #9c27b0; padding: 10px; }
.align-self-item { background: #9c27b0; color: white; padding: 15px; margin: 5px; border-radius: 4px; text-align: center; width: 80px; }
.align-self-stretch { align-self: stretch; } .align-self-start { align-self: flex-start; } .align-self-end { align-self: flex-end; } .align-self-center { align-self: center; } .align-self-baseline { align-self: baseline; } </style>
<h4>父容器 align-items: center,子項目使用不同的 align-self</h4> <div class="align-self-container"> <div class="align-self-item">預設</div> <div class="align-self-item align-self-start">flex-start</div> <div class="align-self-item align-self-end">flex-end</div> <div class="align-self-item align-self-stretch">stretch</div> <div class="align-self-item align-self-baseline">baseline</div> </div>
|
子元素屬性學習重點
- flex-basis:設定基礎尺寸,優先級高於 width/height
- flex-grow:分配剩餘空間,按比例計算
- flex-shrink:收縮空間,按比例計算
- flex 簡寫:快速設置常用組合
- order:改變視覺順序而不修改 HTML
- align-self:單獨控制項目的交叉軸對齊
FlexBox 實際應用案例
在學習完 FlexBox 的基本語法與屬性後,實際應用才是鞏固觀念的最佳方式。以下將透過多個常見的實務案例,帶你一步步了解如何運用 FlexBox 解決日常網頁排版的各種需求,從基礎到進階,讓你能靈活掌握彈性盒子的強大威力。
基礎應用案例
以下是 FlexBox 在實際專案中的常見應用,從基礎到進階逐步展示:
案例一:完美居中的登入表單
傳統的垂直居中一直是 CSS 的難題,但 FlexBox 讓這變得極其簡單:
perfect-center-login.html<style> .login-container { display: flex; justify-content: center; align-items: center; min-height: 100vh; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 20px; }
.login-form { background: white; padding: 40px; border-radius: 12px; box-shadow: 0 8px 32px rgba(0,0,0,0.1); width: 100%; max-width: 400px; }
.login-title { text-align: center; color: #2c3e50; margin-bottom: 30px; font-size: 1.8rem; }
.form-group { margin-bottom: 20px; }
.form-label { display: block; margin-bottom: 5px; color: #555; font-weight: 500; }
.form-input { width: 100%; padding: 12px; border: 2px solid #e1e8ed; border-radius: 8px; font-size: 1rem; transition: border-color 0.3s; }
.form-input:focus { outline: none; border-color: #667eea; }
.form-actions { display: flex; gap: 12px; margin-top: 25px; }
.btn { flex: 1; padding: 12px; border: none; border-radius: 8px; font-size: 1rem; cursor: pointer; transition: all 0.3s; }
.btn-primary { background: #667eea; color: white; }
.btn-primary:hover { background: #5a67d8; }
.btn-secondary { background: #e2e8f0; color: #4a5568; }
.btn-secondary:hover { background: #cbd5e0; } </style>
<div class="login-container"> <form class="login-form"> <h2 class="login-title">會員登入</h2> <div class="form-group"> <label class="form-label">電子郵件</label> <input type="email" class="form-input" placeholder="請輸入您的電子郵件"> </div> <div class="form-group"> <label class="form-label">密碼</label> <input type="password" class="form-input" placeholder="請輸入您的密碼"> </div> <div class="form-actions"> <button type="button" class="btn btn-secondary">取消</button> <button type="submit" class="btn btn-primary">登入</button> </div> </form> </div>
|
FlexBox 的優勢展現
- 只需要 3 行 CSS 就能完美居中
- 無需複雜的計算和定位
- 自動適應內容大小
- 完美的響應式行為
案例二:彈性導航選單
FlexBox 讓導航選單的製作變得極其簡單和彈性:
flexible-navigation.html<style> .navbar { display: flex; justify-content: space-between; align-items: center; background: #2c3e50; color: white; padding: 15px 30px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
.nav-brand { font-size: 1.5rem; font-weight: bold; color: #3498db; }
.nav-menu { display: flex; list-style: none; gap: 30px; margin: 0; padding: 0; }
.nav-menu a { color: white; text-decoration: none; padding: 8px 16px; border-radius: 4px; transition: background 0.3s; }
.nav-menu a:hover { background: rgba(52, 152, 219, 0.2); color: #3498db; }
.nav-actions { display: flex; gap: 15px; }
.nav-btn { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; font-size: 0.9rem; transition: background 0.3s; }
.nav-btn-primary { background: #3498db; color: white; }
.nav-btn-secondary { background: transparent; color: white; border: 1px solid white; }
.nav-btn:hover { opacity: 0.8; }
@media (max-width: 768px) { .navbar { flex-direction: column; gap: 15px; } .nav-menu { gap: 15px; } .nav-actions { order: -1; } } </style>
<nav class="navbar"> <div class="nav-brand">MyWebsite</div> <ul class="nav-menu"> <li><a href="#">首頁</a></li> <li><a href="#">關於我們</a></li> <li><a href="#">服務項目</a></li> <li><a href="#">聯絡我們</a></li> </ul> <div class="nav-actions"> <button class="nav-btn nav-btn-outline">登入</button> <button class="nav-btn nav-btn-primary">註冊</button> </div> </nav>
|
彈性導航的優勢
- 自動分配空間,左中右完美對齊
- 響應式設計只需幾行媒體查詢
- 項目可以靈活調整順序
- 間距統一且易於調整
案例三:自適應卡片布局
FlexBox 讓卡片布局變得極其靈活,自動適應不同內容長度:
adaptive-cards.html<style> .card-container { display: flex; flex-wrap: wrap; gap: 20px; padding: 20px; background: #f8f9fa; border-radius: 10px; }
.card { flex: 1 1 300px; background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.1); transition: transform 0.3s, box-shadow 0.3s; display: flex; flex-direction: column; }
.card:hover { transform: translateY(-5px); box-shadow: 0 8px 30px rgba(0,0,0,0.15); }
.card-header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; text-align: center; }
.card-title { margin: 0; font-size: 1.4rem; font-weight: 600; }
.card-subtitle { margin: 5px 0 0 0; opacity: 0.9; font-size: 0.9rem; }
.card-body { padding: 20px; flex-grow: 1; display: flex; flex-direction: column; }
.card-text { color: #6c757d; line-height: 1.6; margin-bottom: 15px; flex-grow: 1; }
.card-footer { display: flex; justify-content: space-between; align-items: center; margin-top: auto; padding-top: 15px; border-top: 1px solid #e9ecef; }
.card-price { font-size: 1.5rem; font-weight: bold; color: #e74c3c; }
.card-btn { padding: 10px 20px; background: #28a745; color: white; border: none; border-radius: 6px; cursor: pointer; transition: background 0.3s; }
.card-btn:hover { background: #218838; }
.card.featured { flex-basis: 100%; flex-direction: row; max-width: none; }
.card.featured .card-header { flex: 0 0 200px; display: flex; flex-direction: column; justify-content: center; }
.card.featured .card-body { flex: 1; }
@media (max-width: 768px) { .card.featured { flex-direction: column; } .card.featured .card-header { flex: none; } } </style>
<div class="card-container"> <div class="card featured"> <div class="card-header"> <h3 class="card-title">特色服務</h3> <p class="card-subtitle">限時優惠</p> </div> <div class="card-body"> <p class="card-text"> 這是我們的特色服務,提供完整的解決方案。具有豐富的功能和優秀的性能表現,能夠滿足您的各種需求。 </p> <div class="card-footer"> <div class="card-price">$199</div> <button class="card-btn">立即購買</button> </div> </div> </div>
<div class="card"> <div class="card-header"> <h3 class="card-title">基礎方案</h3> <p class="card-subtitle">適合個人</p> </div> <div class="card-body"> <p class="card-text"> 最適合個人使用的基礎方案,包含所有必要的功能。 </p> <div class="card-footer"> <div class="card-price">$99</div> <button class="card-btn">選擇方案</button> </div> </div> </div>
<div class="card"> <div class="card-header"> <h3 class="card-title">專業方案</h3> <p class="card-subtitle">適合企業</p> </div> <div class="card-body"> <p class="card-text"> 專為企業設計的專業方案,提供更多高級功能和技術支持,幫助您的業務快速成長。 </p> <div class="card-footer"> <div class="card-price">$299</div> <button class="card-btn">選擇方案</button> </div> </div> </div>
<div class="card"> <div class="card-header"> <h3 class="card-title">高級方案</h3> <p class="card-subtitle">全功能</p> </div> <div class="card-body"> <p class="card-text"> 包含所有功能的高級方案。 </p> <div class="card-footer"> <div class="card-price">$499</div> <button class="card-btn">選擇方案</button> </div> </div> </div> </div>
|
自適應卡片的彈性特色
- 自動調整寬度,最小 300px
- 內容長度不同也能保持對齊
- 特色卡片可以跨越整行
- 響應式設計自動適配
實用技巧展示
技巧一:等高布局
過去需要複雜技巧的等高布局,現在輕鬆實現:
equal-height-layout.html<style> .equal-height-container { display: flex; gap: 20px; padding: 20px; background: #f8f9fa; border-radius: 8px; }
.equal-height-item { flex: 1; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); display: flex; flex-direction: column; }
.item-header { background: #3498db; color: white; padding: 15px; margin: -20px -20px 20px -20px; border-radius: 8px 8px 0 0; text-align: center; }
.item-content { flex-grow: 1; color: #6c757d; line-height: 1.6; margin-bottom: 15px; }
.item-footer { margin-top: auto; padding-top: 15px; border-top: 1px solid #e9ecef; text-align: center; }
.item-btn { padding: 10px 20px; background: #28a745; color: white; border: none; border-radius: 5px; cursor: pointer; transition: background 0.3s; }
.item-btn:hover { background: #218838; } </style>
<div class="equal-height-container"> <div class="equal-height-item"> <div class="item-header"> <h4>短內容</h4> </div> <div class="item-content"> 這是一個較短的內容。 </div> <div class="item-footer"> <button class="item-btn">查看更多</button> </div> </div>
<div class="equal-height-item"> <div class="item-header"> <h4>中等內容</h4> </div> <div class="item-content"> 這是一個中等長度的內容,比第一個稍微長一些,但不會太長。 </div> <div class="item-footer"> <button class="item-btn">查看更多</button> </div> </div>
<div class="equal-height-item"> <div class="item-header"> <h4>長內容</h4> </div> <div class="item-content"> 這是一個較長的內容,包含了更多的文字和說明。FlexBox 會自動讓所有項目保持相同的高度,不管內容長短如何。這種等高布局在過去需要複雜的 JavaScript 或 CSS 技巧才能實現。 </div> <div class="item-footer"> <button class="item-btn">查看更多</button> </div> </div> </div>
|
技巧二:彈性的聖杯布局
flexible-holy-grail.html<style> .page-layout { display: flex; flex-direction: column; min-height: 100vh; }
.page-header { background: #2c3e50; color: white; padding: 20px; text-align: center; }
.page-main { display: flex; flex: 1; gap: 20px; padding: 20px; background: #ecf0f1; }
.page-sidebar { flex: 0 0 200px; background: #34495e; color: white; padding: 20px; border-radius: 8px; }
.page-content { flex: 1; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.page-ads { flex: 0 0 150px; background: #f39c12; color: white; padding: 20px; border-radius: 8px; text-align: center; }
.page-footer { background: #2c3e50; color: white; padding: 20px; text-align: center; }
@media (max-width: 768px) { .page-main { flex-direction: column; } .page-sidebar, .page-ads { flex: none; order: 2; } .page-content { order: 1; } } </style>
<div class="page-layout"> <header class="page-header"> <h1>FlexBox 聖杯布局</h1> </header>
<main class="page-main"> <aside class="page-sidebar"> <h3>側邊欄</h3> <p>固定寬度 200px</p> </aside>
<section class="page-content"> <h2>主要內容</h2> <p>這是主要內容區域,會自動佔滿剩餘空間。FlexBox 讓聖杯布局變得極其簡單,不需要複雜的 float 或 positioning 技巧。</p> <p>無論側邊欄內容多少,主要內容都會自動調整寬度。</p> </section>
<aside class="page-ads"> <h4>廣告區</h4> <p>固定寬度 150px</p> </aside> </main>
<footer class="page-footer"> <p>© 2024 FlexBox 示例</p> </footer> </div>
|
技巧三:完美的按鈕組
perfect-button-group.html<style> .button-groups { display: flex; flex-direction: column; gap: 30px; padding: 20px; }
.button-group { display: flex; gap: 10px; padding: 20px; background: #f8f9fa; border-radius: 8px; }
.button-group h4 { margin: 0 0 15px 0; color: #2c3e50; }
.btn { padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 1rem; transition: all 0.3s; }
.btn-primary { background: #3498db; color: white; }
.btn-success { background: #27ae60; color: white; }
.btn-danger { background: #e74c3c; color: white; }
.btn-secondary { background: #95a5a6; color: white; }
.btn:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0,0,0,0.2); }
.equal-width .btn { flex: 1; }
.centered { justify-content: center; }
.space-between { justify-content: space-between; }
.right-aligned { justify-content: flex-end; }
@media (max-width: 768px) { .responsive { flex-direction: column; } .responsive .btn { width: 100%; } } </style>
<div class="button-groups"> <div class="button-group"> <h4>基本按鈕組</h4> <button class="btn btn-primary">主要</button> <button class="btn btn-success">成功</button> <button class="btn btn-danger">危險</button> <button class="btn btn-secondary">次要</button> </div>
<div class="button-group equal-width"> <h4>等寬按鈕組</h4> <button class="btn btn-primary">確認</button> <button class="btn btn-secondary">取消</button> </div>
<div class="button-group centered"> <h4>居中按鈕組</h4> <button class="btn btn-primary">上一步</button> <button class="btn btn-success">下一步</button> </div>
<div class="button-group space-between"> <h4>兩端對齊</h4> <button class="btn btn-secondary">返回</button> <button class="btn btn-primary">完成</button> </div>
<div class="button-group right-aligned"> <h4>右對齊</h4> <button class="btn btn-secondary">取消</button> <button class="btn btn-primary">儲存</button> </div>
<div class="button-group responsive"> <h4>響應式按鈕組</h4> <button class="btn btn-primary">選項一</button> <button class="btn btn-success">選項二</button> <button class="btn btn-danger">選項三</button> </div> </div>
|
FlexBox 的核心價值
FlexBox 解決的傳統難題
- 垂直居中:從複雜變成 3 行代碼
- 等高布局:自動實現,無需 JavaScript
- 彈性分配:空間自動分配,響應式天然
- 對齊控制:強大的對齊系統,精確控制
- 順序調整:視覺順序與 HTML 順序分離
FlexBox 的學習重點
- 理解主軸和交叉軸的概念
- 掌握父容器和子元素的屬性
- 學會運用彈性特性解決實際問題
- 結合響應式設計創造更好的用戶體驗
透過這些實際案例,我們可以清楚看到 FlexBox 在現代網頁開發中的重要地位。它不僅簡化了複雜的布局需求,更提供了前所未有的彈性和控制能力。
學習資源推薦
以下整理幾個優質的線上互動練習網站,抓準 flex 技巧,做一下最後練習。
透過遊戲方式共 24 關卡,學習 CSS 的 flex box 技巧,全球著名的練習遊戲。
透過遊戲方式共 12 關卡,學習 CSS 的 flex box 技巧,幫助思考並加強 CSS 排版上的各種雜症。
透過遊戲方式共兩總模式分別為 20 與 30 關卡,來自六角學院出處。
網格布局 CSS Grid
CSS Grid 是現代網頁設計中最強大的二維布局系統,它徹底改變了我們思考和實現複雜布局的方式。與 FlexBox 專注於一維布局不同,Grid 可以同時控制行和列,讓我們能夠創建真正的二維布局。
CSS Grid 核心概念圖解
首先,我們透過圖片來理解 CSS Grid 的核心概念:

四個重要名詞解釋
Grid 的四個核心概念
- Grid Lines(格線):構成網格的水平和垂直線,是整個網格系統的基礎
- Grid Tracks(軌道):相鄰兩條格線之間的空間,可以是行軌道或列軌道
- Grid Areas(區域):由四條格線圍成的矩形空間,可以包含一個或多個格子
- Grid Cells(格子):最小的網格單位,由相鄰的行線和列線圍成
基礎概念理解
grid-concept-demo.html<style> .concept-demo { display: grid; grid-template-columns: 100px 150px 100px; grid-template-rows: 80px 100px 80px; gap: 10px; padding: 20px; background: #f8f9fa; border: 2px solid #6c757d; position: relative; }
.concept-item { background: rgba(52, 152, 219, 0.3); border: 2px solid #3498db; color: #2c3e50; padding: 10px; border-radius: 4px; text-align: center; font-weight: bold; display: flex; align-items: center; justify-content: center; }
.concept-explanation { margin: 20px 0; padding: 15px; background: #e8f4f8; border-radius: 6px; border-left: 4px solid #3498db; } </style>
<div class="concept-demo"> <div class="concept-item">格子 1</div> <div class="concept-item">格子 2</div> <div class="concept-item">格子 3</div> <div class="concept-item">格子 4</div> <div class="concept-item">格子 5</div> <div class="concept-item">格子 6</div> <div class="concept-item">格子 7</div> <div class="concept-item">格子 8</div> <div class="concept-item">格子 9</div> </div>
<div class="concept-explanation"> <strong>觀察重點:</strong><br> • 這個網格有 4 條垂直格線(列線)和 4 條水平格線(行線)<br> • 共有 3 個列軌道和 3 個行軌道<br> • 總共 9 個格子<br> • 每個格子都是一個獨立的區域 </div>
|
實際操作:使用 DevTools 觀察 Grid
- 在上方範例的網格容器上按 F12 打開開發者工具
- 在 Elements 面板中找到任一
.concept-item
元素
- 在 HTML 標籤旁邊會看到一個
grid
標籤
- 點擊
grid
標籤,頁面上會顯示格線的視覺化效果
- 在 Styles 面板中可以看到 Grid 相關的屬性
父容器屬性
在進入 CSS Grid 的父容器屬性詳細說明之前,讓我們先釐清「父容器」在 Grid 布局中的角色。Grid 的強大之處在於它能夠讓父容器(Grid Container)直接控制子元素(Grid Items)的排列方式,無論是行還是列,都能精確掌控。只要將 display 設為 grid
或 inline-grid
,父容器就會啟動 Grid 模式,子元素自動成為網格項目,這是所有 Grid 屬性的基礎。
小技巧:父容器與子元素的關係
只要父元素設定了 display: grid;
,其所有直接子元素都會自動成為 Grid 項目,無需額外標記 class 或 id。
display 屬性
啟用 Grid 布局的基礎屬性:
.container { display: grid; display: inline-grid; }
|
grid-template-columns 和 grid-template-rows
在設計 CSS Grid 布局時,首先要決定網格需要幾個「格子」(Grid Cell),這會影響你要設定多少「列」(columns)和「行」(rows)。利用下方的語法,我們可以清楚地定義網格的列與行軌道,靈活打造出所需的版面結構。
基本單位介紹
CSS Grid 提供了多種單位來定義軌道尺寸,每種都有其特定的用途:
Grid 可用單位說明
在 CSS Grid 中,您可以透過 grid-template-columns
或 grid-template-rows
屬性,搭配多種單位來指定每一行或每一列的寬度與高度。常見單位如下:
px
:像素,絕對固定長度,適合需要精確尺寸時使用。
%
:百分比,依據父容器的尺寸自動調整,適合響應式設計。
fr
:Fraction(比例單位),代表可用空間的分配份數,是 Grid 專屬的彈性單位。
auto
:自動根據內容大小調整。
em
、rem
:相對於字體大小的單位,適合字型或間距的彈性設計。
min-content
、max-content
、minmax()
:根據內容最小/最大尺寸自動調整,或設定範圍。
basic-units-demo.html<style> .units-demo { display: grid; gap: 15px; padding: 20px; background: #f8f9fa; border: 2px solid #6c757d; margin: 20px 0; }
.units-item { background: #007bff; color: white; padding: 15px; border-radius: 6px; text-align: center; font-weight: bold; }
.fixed-size { grid-template-columns: 100px 200px 150px; grid-template-rows: 80px 120px; }
.flexible-size { grid-template-columns: 1fr 2fr 1fr; grid-template-rows: 100px 200px; }
.mixed-size { grid-template-columns: 150px 1fr 100px; grid-template-rows: auto 150px; }
.percentage-size { grid-template-columns: 25% 50% 25%; grid-template-rows: 30% 70%; }
.content-size { grid-template-columns: min-content max-content minmax(200px, 1fr); grid-template-rows: 80px 120px; }
.minmax-size { grid-template-columns: minmax(100px, 200px) minmax(150px, 1fr) minmax(80px, 120px); grid-template-rows: minmax(60px, auto) minmax(80px, 120px); } </style>
<h4>固定尺寸:100px 200px 150px</h4> <div class="units-demo fixed-size"> <div class="units-item">100px</div> <div class="units-item">200px</div> <div class="units-item">150px</div> <div class="units-item">項目 4</div> <div class="units-item">項目 5</div> <div class="units-item">項目 6</div> </div>
<h4>彈性尺寸:1fr 2fr 1fr</h4> <div class="units-demo flexible-size"> <div class="units-item">1fr</div> <div class="units-item">2fr (更寬)</div> <div class="units-item">1fr</div> <div class="units-item">項目 4</div> <div class="units-item">項目 5</div> <div class="units-item">項目 6</div> </div>
<h4>混合尺寸:150px 1fr 100px</h4> <div class="units-demo mixed-size"> <div class="units-item">150px</div> <div class="units-item">1fr (彈性)</div> <div class="units-item">100px</div> <div class="units-item">auto 高度</div> <div class="units-item">會根據內容調整</div> <div class="units-item">150px 固定</div> </div>
<h4>百分比尺寸:25% 50% 25%</h4> <div class="units-demo percentage-size"> <div class="units-item">25%</div> <div class="units-item">50%</div> <div class="units-item">25%</div> <div class="units-item">30% 高</div> <div class="units-item">70% 高</div> <div class="units-item">項目 6</div> </div>
<h4>內容自適應:min-content max-content minmax(200px, 1fr)</h4> <div class="units-demo content-size"> <div class="units-item">短文字</div> <div class="units-item">這是一個很長的文字內容,用來測試 max-content 的效果</div> <div class="units-item">彈性範圍</div> <div class="units-item">項目 4</div> <div class="units-item">項目 5</div> <div class="units-item">項目 6</div> </div>
<h4>minmax 函數:minmax(100px, 200px) minmax(150px, 1fr) minmax(80px, 120px)</h4> <div class="units-demo minmax-size"> <div class="units-item">最小 100px<br>最大 200px</div> <div class="units-item">最小 150px<br>彈性最大</div> <div class="units-item">最小 80px<br>最大 120px</div> <div class="units-item">自動高度</div> <div class="units-item">項目 5</div> <div class="units-item">項目 6</div> </div>
|
基本單位使用建議
- 固定布局:使用
px
確保精確尺寸
- 響應式設計:使用
%
和 fr
實現彈性布局
- 內容自適應:使用
auto
、min-content
、max-content
讓內容決定尺寸
- 範圍控制:使用
minmax()
設定最小和最大尺寸
- 混合策略:結合不同單位創造最佳效果
內容自適應單位的詳細說明
- min-content:使用內容的最小可能尺寸(通常是單個單詞的寬度)
- max-content:使用內容的最大可能尺寸(通常是完整內容的寬度)
- minmax(min, max):設定最小值和最大值,讓軌道在這個範圍內彈性調整
- auto:根據內容自動調整,類似於傳統的塊級元素行為
repeat() 函數用法
repeat()
函數是 CSS Grid 的強大工具,可以快速重複指定的軌道定義,大幅簡化程式碼:
repeat() 函數語法
常用模式:
repeat(3, 1fr)
:重複 3 次,每次 1fr
repeat(auto-fit, minmax(200px, 1fr))
:自動填充,最小 200px
repeat(auto-fill, 150px)
:自動填充,固定 150px
repeat-function-demo.html<style> .repeat-demo { display: grid; gap: 15px; padding: 20px; background: #f8f9fa; border: 2px solid #6c757d; margin: 20px 0; }
.repeat-item { background: #28a745; color: white; padding: 15px; border-radius: 6px; text-align: center; font-weight: bold; }
.basic-repeat { grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(2, 100px); }
.mixed-repeat { grid-template-columns: 200px repeat(3, 1fr) 150px; grid-template-rows: repeat(3, 80px); }
.auto-fit { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); grid-template-rows: repeat(2, 100px); }
.auto-fill { grid-template-columns: repeat(auto-fill, 150px); grid-template-rows: repeat(2, 80px); }
.complex-repeat { grid-template-columns: repeat(2, 1fr 2fr); grid-template-rows: repeat(3, 60px); } </style>
<h4>基本重複:repeat(4, 1fr)</h4> <div class="repeat-demo basic-repeat"> <div class="repeat-item">1</div> <div class="repeat-item">2</div> <div class="repeat-item">3</div> <div class="repeat-item">4</div> <div class="repeat-item">5</div> <div class="repeat-item">6</div> <div class="repeat-item">7</div> <div class="repeat-item">8</div> </div>
<h4>混合重複:200px repeat(3, 1fr) 150px</h4> <div class="repeat-demo mixed-repeat"> <div class="repeat-item">200px</div> <div class="repeat-item">1fr</div> <div class="repeat-item">150px</div> <div class="repeat-item">項目 6</div> <div class="repeat-item">項目 7</div> <div class="repeat-item">項目 8</div> <div class="repeat-item">項目 9</div> </div>
<h4>自動填充:repeat(auto-fit, minmax(200px, 1fr))</h4> <div class="repeat-demo auto-fit"> <div class="repeat-item">自動適應</div> <div class="repeat-item">最小 200px</div> <div class="repeat-item">彈性分配</div> <div class="repeat-item">響應式</div> <div class="repeat-item">項目 5</div> <div class="repeat-item">項目 6</div> </div>
<h4>自動填充固定:repeat(auto-fill, 150px)</h4> <div class="repeat-demo auto-fill"> <div class="repeat-item">固定 150px</div> <div class="repeat-item">自動填充</div> <div class="repeat-item">項目 3</div> <div class="repeat-item">項目 4</div> <div class="repeat-item">項目 5</div> <div class="repeat-item">項目 6</div> </div>
<h4>複雜重複:repeat(2, 1fr 2fr)</h4> <div class="repeat-demo complex-repeat"> <div class="repeat-item">1fr</div> <div class="repeat-item">2fr</div> <div class="repeat-item">1fr</div> <div class="repeat-item">2fr</div> <div class="repeat-item">項目 5</div> <div class="repeat-item">項目 6</div> </div>
|
repeat() 函數的優勢
- 程式碼簡潔:避免重複寫相同的值
- 維護性高:修改重複次數只需改一個數字
- 響應式友好:auto-fit 和 auto-fill 實現自動適應
- 靈活性強:可以混合使用固定值和重複模式
auto-fit 與 auto-fill 詳細對比
這兩個關鍵字在 repeat()
函數中的行為差異是 CSS Grid 的重要概念,理解它們的差異對於創建響應式布局至關重要:
核心差異說明
- auto-fit:會「收縮」空的軌道,讓現有內容填滿可用空間
- auto-fill:會「保持」所有可能的軌道,即使沒有內容填充
- 這個差異在內容數量少於可用軌道時最明顯
兩者差異對比
讓我們透過具體的應用場景來理解兩者的差異:
practical-comparison.html<style> .practical-demo { margin: 30px 0; }
.scenario { background: #f8f9fa; border: 2px solid #6c757d; border-radius: 8px; padding: 20px; margin: 20px 0; }
.scenario h4 { color: #2c3e50; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #3498db; }
.card-grid { display: grid; gap: 15px; padding: 15px; background: white; border-radius: 6px; min-height: 150px; }
.auto-fit-cards { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.auto-fill-cards { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
.card { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px; text-align: center; font-weight: bold; }
.use-case { background: #e8f5e8; padding: 15px; border-radius: 6px; margin: 15px 0; border-left: 4px solid #28a745; }
.avoid-case { background: #fff5f5; padding: 15px; border-radius: 6px; margin: 15px 0; border-left: 4px solid #dc3545; } </style>
<div class="practical-demo"> <h3>實際應用場景對比</h3>
<div class="scenario"> <h4>📱 響應式卡片布局</h4> <div class="card-grid auto-fit-cards"> <div class="card">產品卡片 1</div> <div class="card">產品卡片 2</div> <div class="card">產品卡片 3</div> </div> <div class="use-case"> <strong>✅ 使用 auto-fit 的優勢:</strong><br> • 卡片會自動填滿可用空間<br> • 在大螢幕上卡片會變寬<br> • 在小螢幕上會自動換行<br> • 視覺效果更自然 </div> </div>
<div class="scenario"> <h4>🎨 圖片畫廊布局</h4> <div class="card-grid auto-fill-cards"> <div class="card">圖片 1</div> <div class="card">圖片 2</div> <div class="card">圖片 3</div> </div> <div class="use-case"> <strong>✅ 使用 auto-fill 的優勢:</strong><br> • 保持固定的圖片尺寸<br> • 為未來添加的圖片預留空間<br> • 適合動態載入內容<br> • 布局更穩定 </div> </div>
<div class="scenario"> <h4>💡 選擇建議</h4> <div class="use-case"> <strong>使用 auto-fit 當:</strong><br> • 內容數量相對固定<br> • 希望內容填滿可用空間<br> • 需要響應式的視覺效果<br> • 大多數響應式設計場景 </div> <div class="avoid-case"> <strong>使用 auto-fill 當:</strong><br> • 內容數量會動態變化<br> • 需要保持固定的項目尺寸<br> • 為未來內容預留空間<br> • 需要更穩定的布局 </div> </div> </div>
|
記憶技巧
- auto-fit = “適應內容” → 軌道會收縮適應現有內容
- auto-fill = “填充空間” → 軌道會保持填充所有可能空間
- 在大多數的情況下,auto-fit 是更好的選擇
- 當您只設定 grid-template-columns 而不設定 grid-template-rows 時,Grid 會自動創建行軌道來容納剩餘 cell
auto-fit 常用方式
auto-fit
和 auto-fill
必須搭配 minmax()
,但最大值可以使用不同的單位:
different-combinations.html<style> .combination-demo { margin: 30px 0; }
.combination-section { background: #f8f9fa; border: 2px solid #6c757d; border-radius: 8px; padding: 20px; margin: 20px 0; }
.combination-title { font-weight: bold; color: #2c3e50; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #3498db; }
.combination-grid { display: grid; gap: 10px; padding: 15px; background: white; border-radius: 6px; min-height: 120px; }
.combination-item { background: #007bff; color: white; padding: 15px; border-radius: 6px; text-align: center; font-weight: bold; display: flex; align-items: center; justify-content: center; }
.fr-combination { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.px-combination { grid-template-columns: repeat(auto-fit, minmax(150px, 300px)); }
.percent-combination { grid-template-columns: repeat(auto-fit, minmax(300px, 50%)); }
.auto-combination { grid-template-columns: repeat(auto-fit, minmax(100px, auto)); }
.code-example { background: #f1f3f4; padding: 15px; border-radius: 6px; margin: 15px 0; font-family: 'Courier New', monospace; font-size: 0.9rem; }
.advantage-box { background: #e8f5e8; padding: 15px; border-radius: 6px; margin: 15px 0; border-left: 4px solid #28a745; }
.disadvantage-box { background: #fff5f5; padding: 15px; border-radius: 6px; margin: 15px 0; border-left: 4px solid #dc3545; } </style>
<div class="combination-demo"> <h3>不同搭配方式的對比</h3>
<div class="combination-section"> <div class="combination-title">1. minmax(150px, 1fr) - 最常用</div> <div class="combination-grid fr-combination"> <div class="combination-item">項目 1</div> <div class="combination-item">項目 2</div> <div class="combination-item">項目 3</div> </div> <div class="code-example"> grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); </div> <div class="advantage-box"> <strong>✅ 優勢:</strong><br> • 完全響應式,填滿可用空間<br> • 在大螢幕上會自動變寬<br> • 在小螢幕上會自動換行<br> • 最適合現代響應式設計 </div> </div>
<div class="combination-section"> <div class="combination-title">2. minmax(150px, 300px) - 固定最大寬度</div> <div class="combination-grid px-combination"> <div class="combination-item">項目 1</div> <div class="combination-item">項目 2</div> <div class="combination-item">項目 3</div> </div> <div class="code-example"> grid-template-columns: repeat(auto-fit, minmax(150px, 300px)); </div> <div class="advantage-box"> <strong>✅ 優勢:</strong><br> • 控制最大寬度,避免過寬<br> • 適合需要限制尺寸的設計<br> • 保持一致的視覺效果 </div> <div class="disadvantage-box"> <strong>❌ 限制:</strong><br> • 在大螢幕上可能會有空白空間<br> • 不如 fr 單位那麼彈性 </div> </div>
<div class="combination-section"> <div class="combination-title">3. minmax(300px, 50%) - 百分比範圍</div> <div class="combination-grid percent-combination"> <div class="combination-item">項目 1</div> <div class="combination-item">項目 2</div> <div class="combination-item">項目 3</div> </div> <div class="code-example"> grid-template-columns: repeat(auto-fit, minmax(300px, 50%)); </div> <div class="advantage-box"> <strong>✅ 優勢:</strong><br> • 相對於容器尺寸調整<br> • 適合需要特定比例的設計<br> • 響應式但有限制 </div> </div>
<div class="combination-section"> <div class="combination-title">4. minmax(100px, auto) - 內容自適應</div> <div class="combination-grid auto-combination"> <div class="combination-item">短文字</div> <div class="combination-item">這是一個很長的文字內容,用來測試 auto 的效果</div> <div class="combination-item">項目 3</div> </div> <div class="code-example"> grid-template-columns: repeat(auto-fit, minmax(100px, auto)); </div> <div class="advantage-box"> <strong>✅ 優勢:</strong><br> • 根據內容自動調整寬度<br> • 適合文字內容長度不一的場景<br> • 避免文字被截斷 </div> </div> </div>
|
選擇建議
minmax(150px, 1fr) - 最推薦
- 適用於大多數響應式設計
- 完全填滿可用空間
- 現代網頁設計的標準做法
minmax(150px, 300px) - 需要控制最大寬度時
minmax(20%, 50%) - 需要特定比例時
minmax(100px, auto) - 內容長度不一時
記憶要點
- 必須使用 minmax():auto-fit/auto-fill 需要最小值和最大值
- fr 最常用:提供最大的彈性和響應式效果
- 根據需求選擇:不同的最大值單位適合不同的設計需求
gap 屬性
控制網格項目之間的間距:
gap-demo.html<style> .gap-demo { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(2, 100px); padding: 20px; background: #f8f9fa; border: 2px solid #6c757d; margin: 20px 0; }
.gap-item { background: #28a745; color: white; padding: 15px; border-radius: 6px; text-align: center; font-weight: bold; }
.gap-0 { gap: 0; } .gap-10 { gap: 10px; } .gap-20 { gap: 20px; } .gap-custom { gap: 10px 30px; } </style>
<h4>gap: 0</h4> <div class="gap-demo gap-0"> <div class="gap-item">1</div> <div class="gap-item">2</div> <div class="gap-item">3</div> <div class="gap-item">4</div> <div class="gap-item">5</div> <div class="gap-item">6</div> </div>
<h4>gap: 10px</h4> <div class="gap-demo gap-10"> <div class="gap-item">1</div> <div class="gap-item">2</div> <div class="gap-item">3</div> <div class="gap-item">4</div> <div class="gap-item">5</div> <div class="gap-item">6</div> </div>
<h4>gap: 20px</h4> <div class="gap-demo gap-20"> <div class="gap-item">1</div> <div class="gap-item">2</div> <div class="gap-item">3</div> <div class="gap-item">4</div> <div class="gap-item">5</div> <div class="gap-item">6</div> </div>
<h4>gap: 10px 30px(行間距 列間距)</h4> <div class="gap-demo gap-custom"> <div class="gap-item">1</div> <div class="gap-item">2</div> <div class="gap-item">3</div> <div class="gap-item">4</div> <div class="gap-item">5</div> <div class="gap-item">6</div> </div>
|
grid-template-areas 屬性
使用語義化的區域名稱(area name)可以讓 CSS Grid 佈局更直觀易懂。只需在父容器設定 grid-template-areas
屬性,利用雙引號分行(每行代表一列,行內以空格分隔各欄),即可規劃每個區塊的排列方式。接著,為每個子元素指定對應的 grid-area
名稱,瀏覽器就會自動將元素放置到指定的網格區域,讓版面結構一目了然、維護更方便。
areas-demo.html<style> .areas-demo { display: grid; grid-template-areas: "header header header" "sidebar main ads" "footer footer footer"; grid-template-columns: 200px 1fr 150px; grid-template-rows: 80px 1fr 60px; gap: 15px; height: 400px; padding: 20px; background: #f8f9fa; border: 2px solid #343a40; }
.area-item { padding: 20px; border-radius: 8px; color: white; font-weight: bold; text-align: center; display: flex; align-items: center; justify-content: center; }
.area-header { grid-area: header; background: #007bff; }
.area-sidebar { grid-area: sidebar; background: #6c757d; }
.area-main { grid-area: main; background: #28a745; }
.area-ads { grid-area: ads; background: #ffc107; color: #212529; }
.area-footer { grid-area: footer; background: #dc3545; } </style>
<div class="areas-demo"> <div class="area-item area-header">Header</div> <div class="area-item area-sidebar">Sidebar</div> <div class="area-item area-main">Main Content</div> <div class="area-item area-ads">Ads</div> <div class="area-item area-footer">Footer</div> </div>
|
grid-template-areas 的優勢
- 程式碼具有視覺化效果,容易理解
- 便於修改和維護
- 搭配 media query 來實現響應式設計時,可以重新排列區域
- 提升程式碼的可讀性
grid-template 簡寫屬性
grid-template
是 grid-template-rows
、grid-template-columns
和 grid-template-areas
的簡寫屬性,可以同時定義行、列和區域:
grid-template-shorthand.html<style> .shorthand-demo { display: grid; gap: 15px; padding: 20px; background: #f8f9fa; border: 2px solid #6c757d; margin: 20px 0; }
.shorthand-item { background: #28a745; color: white; padding: 15px; border-radius: 6px; text-align: center; font-weight: bold; }
.basic-shorthand { grid-template: 100px 200px / 1fr 2fr 1fr; }
.area-shorthand { grid-template: "header header header" 80px "sidebar main ads" 1fr "footer footer footer" 60px / 200px 1fr 150px; }
.repeat-shorthand { grid-template: repeat(3, 100px) / repeat(4, 1fr); }
.mixed-shorthand { grid-template: "a a b" 80px "c d e" 120px / 1fr 2fr 1fr; }
.area-a { grid-area: a; background: #dc3545; } .area-b { grid-area: b; background: #ffc107; color: #212529; } .area-c { grid-area: c; background: #17a2b8; } .area-d { grid-area: d; background: #6f42c1; } .area-e { grid-area: e; background: #e83e8c; } </style>
<h4>基本簡寫:grid-template: 100px 200px / 1fr 2fr 1fr</h4> <div class="shorthand-demo basic-shorthand"> <div class="shorthand-item">1fr</div> <div class="shorthand-item">2fr</div> <div class="shorthand-item">1fr</div> <div class="shorthand-item">100px 高</div> <div class="shorthand-item">200px 高</div> <div class="shorthand-item">項目 6</div> </div>
<h4>包含區域的簡寫</h4> <div class="shorthand-demo area-shorthand"> <div class="shorthand-item area-a">Header</div> <div class="shorthand-item area-b">Sidebar</div> <div class="shorthand-item area-c">Main</div> <div class="shorthand-item area-d">Ads</div> <div class="shorthand-item area-e">Footer</div> </div>
<h4>使用 repeat 的簡寫:grid-template: repeat(3, 100px) / repeat(4, 1fr)</h4> <div class="shorthand-demo repeat-shorthand"> <div class="shorthand-item">1</div> <div class="shorthand-item">2</div> <div class="shorthand-item">3</div> <div class="shorthand-item">4</div> <div class="shorthand-item">5</div> <div class="shorthand-item">6</div> <div class="shorthand-item">7</div> <div class="shorthand-item">8</div> </div>
<h4>混合使用:grid-template: "a a b" 80px "c d e" 120px / 1fr 2fr 1fr</h4> <div class="shorthand-demo mixed-shorthand"> <div class="shorthand-item area-a">區域 A</div> <div class="shorthand-item area-b">區域 B</div> <div class="shorthand-item area-c">區域 C</div> <div class="shorthand-item area-d">區域 D</div> <div class="shorthand-item area-e">區域 E</div> </div>
|
grid-template 簡寫語法說明
- 基本格式:
grid-template: 行定義 / 列定義
- 包含區域:
grid-template: "區域名稱" 行高 / 列寬
- 多行區域:每行區域定義後跟行高,最後用
/
分隔列定義
- 優勢:程式碼更簡潔,區域定義更直觀
- 注意:使用簡寫時,
grid-template-areas
、grid-template-rows
、grid-template-columns
會被重置
簡寫與完整屬性的對比
shorthand-comparison.html<style> .comparison-demo { display: grid; gap: 15px; padding: 20px; background: #f8f9fa; border: 2px solid #6c757d; margin: 20px 0; }
.comparison-item { background: #007bff; color: white; padding: 15px; border-radius: 6px; text-align: center; font-weight: bold; }
.full-properties { grid-template-areas: "header header" "sidebar main" "footer footer"; grid-template-rows: 80px 1fr 60px; grid-template-columns: 200px 1fr; }
.shorthand-properties { grid-template: "header header" 80px "sidebar main" 1fr "footer footer" 60px / 200px 1fr; }
.area-header { grid-area: header; background: #dc3545; } .area-sidebar { grid-area: sidebar; background: #28a745; } .area-main { grid-area: main; background: #ffc107; color: #212529; } .area-footer { grid-area: footer; background: #6f42c1; } </style>
<h4>完整屬性寫法</h4> <div class="comparison-demo full-properties"> <div class="comparison-item area-header">Header</div> <div class="comparison-item area-sidebar">Sidebar</div> <div class="comparison-item area-main">Main</div> <div class="comparison-item area-footer">Footer</div> </div>
<h4>簡寫屬性寫法</h4> <div class="comparison-demo shorthand-properties"> <div class="comparison-item area-header">Header</div> <div class="comparison-item area-sidebar">Sidebar</div> <div class="comparison-item area-main">Main</div> <div class="comparison-item area-footer">Footer</div> </div>
|
簡寫屬性的使用建議
- 簡單布局:使用基本簡寫
grid-template: 行 / 列
- 複雜區域:使用區域簡寫,程式碼更清晰
- 重複模式:結合
repeat()
函數使用
- 維護性:簡寫屬性讓程式碼更緊湊,但要注意可讀性
空間分布與對齊方式
在 CSS Grid 中,對齊方式主要分為兩大類:內容對齊(Content Alignment) 與 項目對齊(Item Alignment),分別對應到四個屬性:
justify-content
:控制整個網格內容在水平方向上的分布
align-content
:控制整個網格內容在垂直方向上的分布
justify-items
:控制每個格子(cell)內部項目在水平方向上的對齊
align-items
:控制每個格子(cell)內部項目在垂直方向上的對齊
當父容器(Grid 容器)有固定的寬高,且格線尺寸(行與列)也都是固定值(如 px
),這時候容器內部就會產生剩餘空間。你可以透過上述四個屬性,靈活調整整體網格內容與每個格子內部項目的對齊方式,讓版面更符合設計需求。
下圖展示了這四種對齊屬性在不同設定下的排列效果:

justify-content 和 align-content
與 FlexBox(彈性盒模型)相同,CSS Grid 也提供了精確控制父容器內所有子項目整體對齊方式的屬性,可用來調整整個網格在容器中的水平與垂直排列效果。
justify-content 與 align-content 可用的值:
start
:靠容器起始邊對齊(左或上)
end
:靠容器結束邊對齊(右或下)
center
:置中對齊
stretch
:預設值,若有多餘空間則分散填滿(但不會拉伸 grid item 的尺寸,只會分配空白區域)
space-between
:首尾貼齊,項目間平均分配間距
space-around
:每個項目兩側間距相等
space-evenly
:所有間距(含首尾)完全平均
注意事項:
在 CSS Grid 中,stretch
並不會拉伸 grid item 的寬度或高度,只會讓整個 grid content 填滿容器的剩餘空間。若 grid 的尺寸已被內容撐滿,則 stretch
不會有明顯效果。
這些值讓你能靈活調整整個 grid 內容在父容器中的排列方式,類似於 FlexBox 的對齊屬性。
跟著做:
讓我們透過實際範例來了解 justify-content 和 align-content 的效果。
content-alignment.html<style> .content-demo { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(2, 80px); gap: 10px; width: 400px; height: 250px; padding: 20px; background: #f8f9fa; border: 2px solid #6c757d; margin: 20px 0; }
.content-item { background: #007bff; color: white; padding: 10px; border-radius: 4px; text-align: center; font-weight: bold; }
.justify-start { justify-content: start; } .justify-center { justify-content: center; } .justify-end { justify-content: end; } .justify-space-around { justify-content: space-around; } .justify-space-between { justify-content: space-between; } .justify-space-evenly { justify-content: space-evenly; }
.align-start { align-content: start; } .align-center { align-content: center; } .align-end { align-content: end; } </style>
<h4>justify-content: center</h4> <div class="content-demo justify-center"> <div class="content-item">1</div> <div class="content-item">2</div> <div class="content-item">3</div> <div class="content-item">4</div> <div class="content-item">5</div> <div class="content-item">6</div> </div>
<h4>align-content: center</h4> <div class="content-demo align-center"> <div class="content-item">1</div> <div class="content-item">2</div> <div class="content-item">3</div> <div class="content-item">4</div> <div class="content-item">5</div> <div class="content-item">6</div> </div>
<h4>justify-content: center + align-content: center</h4> <div class="content-demo justify-center align-center"> <div class="content-item">1</div> <div class="content-item">2</div> <div class="content-item">3</div> <div class="content-item">4</div> <div class="content-item">5</div> <div class="content-item">6</div> </div>
|
justify-items 和 align-items
當父容器完成格線(grid)定義後,每個子項目會自動被分配到對應的 cell(格子)空間。預設情況下,若子項目未設定寬高,內容會自動以 stretch
模式填滿 cell 的寬度與高度;若有指定寬高,則以內容尺寸為主。透過設定 cell 內的對齊屬性,可以靈活調整子項目在格子中的擺放位置,讓版面更具彈性與美觀。
justify-items 與 align-items 差異與用途說明:
- 這兩個屬性用來「設定每個網格項目(grid item)在自己格子(cell)內的對齊方式」
justify-items
:控制水平方向(格子內左右對齊)
align-items
:控制垂直方向(格子內上下對齊)
常見值:
start
:靠起點對齊
center
:置中對齊
end
:靠終點對齊
stretch
:拉伸填滿(預設值)
小技巧:
- 若未設定寬高,預設為
stretch
,會自動填滿格子空間
- 若有設定寬高,建議搭配
center
或 start
,讓版面更美觀
跟著做:
讓我們透過實際範例來了解 justify-items 和 align-items 的效果。
控制網格項目在各自格子內的對齊方式如下:
items-alignment.html<style> .items-demo { display: grid; grid-template-columns: repeat(3, 150px); grid-template-rows: repeat(2, 100px); gap: 10px; padding: 20px; background: #f8f9fa; border: 2px solid #6c757d; margin: 20px 0; }
.items-item { background: #17a2b8; color: white; padding: 10px; border-radius: 4px; text-align: center; font-weight: bold; width: 80px; height: 50px; }
.justify-items-start { justify-items: start; } .justify-items-center { justify-items: center; } .justify-items-end { justify-items: end; } .justify-items-stretch { justify-items: stretch; }
.align-items-start { align-items: start; } .align-items-center { align-items: center; } .align-items-end { align-items: end; } .align-items-stretch { align-items: stretch; }
.stretch-item { width: auto; height: auto; } </style>
<h4>justify-items: center</h4> <div class="items-demo justify-items-center"> <div class="items-item">1</div> <div class="items-item">2</div> <div class="items-item">3</div> <div class="items-item">4</div> <div class="items-item">5</div> <div class="items-item">6</div> </div>
<h4>align-items: center</h4> <div class="items-demo align-items-center"> <div class="items-item">1</div> <div class="items-item">2</div> <div class="items-item">3</div> <div class="items-item">4</div> <div class="items-item">5</div> <div class="items-item">6</div> </div>
<h4>justify-items: stretch</h4> <div class="items-demo justify-items-stretch"> <div class="items-item stretch-item">1</div> <div class="items-item stretch-item">2</div> <div class="items-item stretch-item">3</div> <div class="items-item stretch-item">4</div> <div class="items-item stretch-item">5</div> <div class="items-item stretch-item">6</div> </div>
|
子元素屬性
本節將帶你深入了解 CSS Grid 子元素(Grid Item)的定位與對齊技巧。掌握這些屬性,你將能靈活控制每個區塊在網格中的位置與排列方式,實現更精細的二維布局。建議先理解父容器的網格結構,再逐步練習子元素的各種定位方法,從基礎到進階,循序漸進。
grid-column 和 grid-row
在 CSS Grid 中,可以利用「格線編號」來精確控制每個子元素(Grid Item)的位置。這種方式讓你能夠指定元素從哪一條格線開始、到哪一條格線結束,靈活實現跨欄、跨列等多樣化的版面配置。
格線編號定位
格線編號定位原理
- 必須先在父容器(Grid Container)定義好行數與列數,瀏覽器會自動產生格線(Grid Line)。
- 子元素可透過
grid-column
和 grid-row
屬性,指定「從第幾條格線開始,到第幾條格線結束」。
- 格線編號從左到右、從上到下都是從
1
開始。
- 也可以用負數,
-1
代表最右邊(或最下方)那條格線,-2
代表倒數第二條,以此類推。
- 這種方式讓你能夠彈性控制元素的跨欄、跨列範圍。
- 正向(如
1 / 3
)與反向(如 3 / 1
或 -1 / 1
)格線編號在 CSS Grid 都是合法的,代表從不同方向跨格線。Grid 會自動計算範圍,讓你靈活控制排列方向。
line-positioning.html<style> .line-demo { display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(3, 100px); gap: 10px; padding: 20px; background: #f8f9fa; border: 2px solid #6c757d; margin: 20px 0; }
.line-item { background: #007bff; color: white; padding: 15px; border-radius: 6px; text-align: center; font-weight: bold; display: flex; align-items: center; justify-content: center; }
.item-1 { grid-column: 1 / 3; grid-row: 1 / 2; background: #dc3545; }
.item-2 { grid-column: 3 / 5; grid-row: 1 / 3; background: #28a745; }
.item-3 { grid-column: 1 / -1; grid-row: 3 / 4; background: #ffc107; color: #212529; }
.item-reverse { grid-column: 3 / 1; grid-row: 2 / 3; background: #ff6666; }
.item-full-reverse { grid-column: -1 / 1; grid-row: 1 / 2; background: #66b3ff; } </style>
<div class="line-demo"> <div class="line-item item-1">正向<br>grid-column: 1 / 3</div> <div class="line-item item-2">正向<br>grid-column: 3 / 5<br>grid-row: 1 / 3</div> <div class="line-item item-3">橫跨整行<br>grid-column: 1 / -1</div> <div class="line-item item-reverse">反向<br>grid-column: 3 / 1</div> <div class="line-item item-full-reverse">全行反向<br>grid-column: -1 / 1</div> <div class="line-item">普通項目</div> </div>
|
當多個 grid item 被放在同一格時,預設會依照 HTML 結構的順序,後面的元素會蓋在前面的元素上。
如果需要自訂圖層順序,可以對特定 item 設定 position: relative
並搭配 z-index
,數值越大層級越高。
.item-3 { grid-column: 1 / -1; grid-row: 3 / 4; background: #ffc107; color: #212529; position: relative; z-index: 10; }
|
使用 span 關鍵字
span
關鍵字可用於 grid-column
或 grid-row
,讓你直接指定元素要「跨越幾條格線」。
- 語法如:
grid-column: span 2;
表示這個元素會橫跨 2 欄(從當前格線起算)。這種寫法不需明確指定結束格線編號,適合動態或不確定結束位置的情境。
span
讓版面配置更具彈性,尤其在自動排版或內容數量不固定時特別實用。
- 也可以指定從哪個格線開始橫跨多行,例如:
grid-row: 2 / span 3;
代表這個元素會從第 2 條格線開始,往下跨 3 行。
span
關鍵字也可以用反向寫法,例如 grid-column: span 2 / 4;
,代表「從第 4 條格線往左跨 2 欄」。Grid 會自動判斷方向並計算範圍,讓你靈活控制元素的排列方式。
span-positioning.html<style> .span-demo { display: grid; grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(4, 80px); gap: 10px; padding: 20px; background: #f8f9fa; border: 2px solid #6c757d; margin: 20px 0; }
.span-item { background: #6f42c1; color: white; padding: 15px; border-radius: 6px; text-align: center; font-weight: bold; display: flex; align-items: center; justify-content: center; }
.span-1 { grid-column: span 2; background: #e83e8c; }
.span-2 { grid-row: span 2; background: #20c997; }
.span-3 { grid-column: 2 / span 3; grid-row: span 2; background: #fd7e14; }
.span-reverse { grid-column: 4 / span 2; background: #ffb366; } </style>
<div class="span-demo"> <div class="span-item span-1">span 2 列</div> <div class="span-item span-2">span 2 行</div> <div class="span-item">普通</div> <div class="span-item span-3">span 3 列 2 行</div> <div class="span-item span-reverse">反向<br>grid-column: 4 / span 2</div> <div class="span-item">普通</div> </div>
|
特定預設值情況
grid-column: span 2;
和 grid-column: auto / span 2;
是等價的,兩者都表示「從自動分配的位置開始,橫跨 2 欄」。
auto
代表「自動由瀏覽器決定起始格線」,通常會接在前一個 item 的右邊(或下方),自動排到下一個可用位置。
.item-a { grid-column: span 2; } .item-b { grid-column: auto / span 2; }
|
grid-row: 2;
、grid-row: 2 / 3;
和 grid-row: 2 / span 1;
都是等價的,表示「從第 2 條格線開始,只佔 1 行」。
span 1
就是「跨 1 格」,和預設行為一致。
.item-a { grid-row: 2; } .item-b { grid-row: 2 / 3; } .item-c { grid-row: 2 / span 1; }
|
原為簡寫屬性
grid-column
和 grid-row
都是簡寫屬性,可以同時設定「start 起始格線」和「end 結束格線」。理解這一點,能幫助你更靈活地控制元素在網格中的位置,也能更快看懂他人寫的 Grid 代碼。這種簡寫方式讓語法更精簡,也更容易閱讀與維護。建議在實務上多加練習,熟悉這兩種寫法的轉換。
以下範例展示簡寫與完整寫法的等價關係:
.item { grid-column: 2 / 4; grid-row: 1 / 3; }
.item { grid-column-start: 2; grid-column-end: 4; grid-row-start: 1; grid-row-end: 3; }
.item { grid-column: span 2; }
.item { grid-column-start: auto; grid-column-end: span 2; }
.item { grid-row: 2 / span 3; }
.item { grid-row-start: 2; grid-row-end: span 3; }
|
span
關鍵字可以讓你用更直覺的方式指定元素要跨越幾條格線。無論是 grid-column
或 grid-row
,都能用 span
來簡化語法,對應的完整寫法則是將 grid-column-end
或 grid-row-end
設為 span N
。
grid-area
稍早示範過,這是可以搭配父屬性的grid-template-areas
使用區域名稱定位。
grid-area-demo.html<style> .area-positioning { display: grid; grid-template-areas: "header header nav" "sidebar main main" "sidebar footer footer"; grid-template-columns: 200px 1fr 150px; grid-template-rows: 80px 1fr 60px; gap: 15px; height: 300px; padding: 20px; background: #f8f9fa; border: 2px solid #343a40; margin: 20px 0; }
.area-positioned { padding: 15px; border-radius: 6px; color: white; font-weight: bold; text-align: center; display: flex; align-items: center; justify-content: center; }
.positioned-header { grid-area: header; background: #007bff; }
.positioned-nav { grid-area: nav; background: #6c757d; }
.positioned-sidebar { grid-area: sidebar; background: #28a745; }
.positioned-main { grid-area: main; background: #dc3545; }
.positioned-footer { grid-area: footer; background: #ffc107; color: #212529; } </style>
<div class="area-positioning"> <div class="area-positioned positioned-header">Header</div> <div class="area-positioned positioned-nav">Nav</div> <div class="area-positioned positioned-sidebar">Sidebar</div> <div class="area-positioned positioned-main">Main</div> <div class="area-positioned positioned-footer">Footer</div> </div>
|
除此之外你也可以作為四個格線值的簡寫,這四個值的順序分別代表不同的起始與結束之格線位置。
.item { grid-area: 2 / 2 / 4 / 4; }
|
grid-area 參數數量與預設行為說明
- 只寫一個值,代表「區域名稱」,用於 grid-template-areas 對應
- 兩個值,等同於只設起始
grid-row-start / grid-column-start
,結束格線預設 auto(只佔一格)。
- 三個值,等同於
grid-row-start / grid-column-start / grid-row-end
,column-end 預設為 auto。
- 四個值,分別對應四個格線,完全自訂範圍。
.item1 { grid-area: main; } .item2 { grid-area: 2 / 3; } .item3 { grid-area: 2 / 3 / 4; } .item4 { grid-area: 2 / 3 / 4 / 5; }
|
justify-self 和 align-self
與 FlexBox(彈性盒模型)相同觀念,可擺脫父屬性的 justify-items 和 align-items,以自身要求來調整對其方式。控制單個網格項目的對齊方式:
self-alignment.html<style> .self-demo { display: grid; grid-template-columns: repeat(3, 150px); grid-template-rows: repeat(2, 100px); gap: 10px; padding: 20px; background: #f8f9fa; border: 2px solid #6c757d; margin: 20px 0; }
.self-item { background: #17a2b8; color: white; padding: 10px; border-radius: 4px; text-align: center; font-weight: bold; width: 80px; height: 50px; }
.self-start { justify-self: start; align-self: start; background: #dc3545; }
.self-center { justify-self: center; align-self: center; background: #28a745; }
.self-end { justify-self: end; align-self: end; background: #ffc107; color: #212529; }
.self-stretch { justify-self: stretch; align-self: stretch; background: #6f42c1; width: auto; height: auto; } </style>
<div class="self-demo"> <div class="self-item self-start">start</div> <div class="self-item self-center">center</div> <div class="self-item self-end">end</div> <div class="self-item">預設</div> <div class="self-item self-stretch">stretch</div> <div class="self-item">預設</div> </div>
|
實戰練習
範例一
跟著做:建立一個完整的網頁布局
使用 CSS Grid 建立一個包含頭部、側邊欄、主要內容和頁尾的完整布局。
complete-layout.html<style> .page-layout { display: grid; grid-template-areas: "header header header" "sidebar main ads" "footer footer footer"; grid-template-columns: 250px 1fr 200px; grid-template-rows: 80px 1fr 60px; gap: 20px; min-height: 100vh; padding: 20px; background: #f8f9fa; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.layout-header { grid-area: header; background: #2c3e50; color: white; padding: 20px; border-radius: 8px; display: flex; align-items: center; justify-content: space-between; }
.layout-sidebar { grid-area: sidebar; background: #34495e; color: white; padding: 20px; border-radius: 8px; }
.layout-main { grid-area: main; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.layout-ads { grid-area: ads; background: #e74c3c; color: white; padding: 20px; border-radius: 8px; text-align: center; }
.layout-footer { grid-area: footer; background: #95a5a6; color: white; padding: 20px; border-radius: 8px; text-align: center; }
.nav-links { display: flex; gap: 20px; list-style: none; margin: 0; padding: 0; }
.nav-links a { color: white; text-decoration: none; transition: color 0.3s; }
.nav-links a:hover { color: #3498db; }
.sidebar-menu { list-style: none; margin: 0; padding: 0; }
.sidebar-menu li { margin-bottom: 10px; padding: 10px; background: rgba(255,255,255,0.1); border-radius: 4px; cursor: pointer; transition: background 0.3s; }
.sidebar-menu li:hover { background: rgba(255,255,255,0.2); }
@media (max-width: 768px) { .page-layout { grid-template-areas: "header" "main" "sidebar" "ads" "footer"; grid-template-columns: 1fr; grid-template-rows: auto auto auto auto auto; } } </style>
<div class="page-layout"> <header class="layout-header"> <h1>我的網站</h1> <nav> <ul class="nav-links"> <li><a href="#">首頁</a></li> <li><a href="#">關於</a></li> <li><a href="#">服務</a></li> <li><a href="#">聯絡</a></li> </ul> </nav> </header>
<aside class="layout-sidebar"> <h3>選單</h3> <ul class="sidebar-menu"> <li>網頁設計</li> <li>前端開發</li> <li>後端開發</li> <li>資料庫</li> <li>雲端服務</li> </ul> </aside>
<main class="layout-main"> <h2>CSS Grid 布局完成!</h2> <p>這是一個使用 CSS Grid 建立的完整網頁布局,包含了:</p> <ul> <li>語義化的區域名稱定義</li> <li>響應式設計支援</li> <li>清晰的結構分離</li> <li>易於維護和修改</li> </ul> <p>透過 <code>grid-template-areas</code> 屬性,我們可以用直觀的方式定義布局,程式碼的可讀性大大提升。</p> </main>
<aside class="layout-ads"> <h4>廣告區域</h4> <p>這裡可以放置<br>廣告內容</p> </aside>
<footer class="layout-footer"> <p>© 2024 CSS Grid 教學示例</p> </footer> </div>
|
範例二
跟著做:建立現代響應式布局
請使用 Grid 和 FlexBox 建立一個包含以下元素的頁面:
- 頭部導航(使用 FlexBox)
- 主要內容區域(使用 Grid)
- 卡片列表(使用 FlexBox)
- 頁尾(使用 FlexBox)
final-practice.html<style> * { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; }
.container { display: grid; grid-template-rows: auto 1fr auto; min-height: 100vh; }
.header { background: #2c3e50; color: white; padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; }
.nav-links { display: flex; list-style: none; gap: 2rem; }
.nav-links a { color: white; text-decoration: none; transition: color 0.3s; }
.nav-links a:hover { color: #3498db; }
.main { display: grid; grid-template-columns: 300px 1fr; gap: 2rem; padding: 2rem; background: #f8f9fa; }
.sidebar { background: white; padding: 1.5rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); height: fit-content; }
.content { background: white; padding: 2rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.card-grid { display: flex; flex-wrap: wrap; gap: 1.5rem; margin-top: 2rem; }
.card { flex: 1 1 300px; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 6px rgba(0,0,0,0.1); transition: transform 0.3s; }
.card:hover { transform: translateY(-5px); }
.card img { width: 100%; height: 200px; object-fit: cover; }
.card-content { padding: 1.5rem; }
.footer { background: #34495e; color: white; padding: 2rem; display: flex; justify-content: center; align-items: center; }
@media (max-width: 768px) { .main { grid-template-columns: 1fr; } .header { flex-direction: column; gap: 1rem; } .nav-links { gap: 1rem; } } </style>
<div class="container"> <header class="header"> <h1>現代布局示例</h1> <nav> <ul class="nav-links"> <li><a href="#">首頁</a></li> <li><a href="#">產品</a></li> <li><a href="#">服務</a></li> <li><a href="#">聯絡</a></li> </ul> </nav> </header>
<main class="main"> <aside class="sidebar"> <h3>分類</h3> <ul> <li>網頁設計</li> <li>前端開發</li> <li>使用者體驗</li> <li>程式開發</li> </ul> </aside>
<section class="content"> <h2>精選內容</h2> <p>這裡展示了現代 CSS 布局技術的強大功能,結合 Grid 和 FlexBox 創造出靈活且響應式的設計。</p> <div class="card-grid"> <div class="card"> <img src="https://picsum.photos/400/200/?random=1" alt="項目 1"> <div class="card-content"> <h3>CSS Grid 教學</h3> <p>學習如何使用 CSS Grid 建立複雜的二維布局。</p> </div> </div> <div class="card"> <img src="https://picsum.photos/400/200/?random=2" alt="項目 2"> <div class="card-content"> <h3>FlexBox 完整指南</h3> <p>掌握 FlexBox 的所有屬性和應用技巧。</p> </div> </div> <div class="card"> <img src="https://picsum.photos/400/200/?random=3" alt="項目 3"> <div class="card-content"> <h3>響應式設計</h3> <p>建立適應各種裝置的現代網頁設計。</p> </div> </div> </div> </section> </main>
<footer class="footer"> <p>© 2024 現代布局教學。使用 Grid 和 FlexBox 技術。</p> </footer> </div>
|
學習重點總結
CSS Grid 學習要點
- 理解基本概念:格線、軌道、區域、格子
- 掌握父容器屬性:定義網格結構和對齊方式
- 熟練子元素定位:使用格線編號、span 或區域名稱
- 善用 DevTools:視覺化觀察網格結構
- 響應式設計:結合媒體查詢重新定義布局
透過這個重新組織的 CSS Grid 教學,您現在應該能夠:
- 理解 Grid 的核心概念和專有名詞
- 使用 DevTools 觀察和除錯 Grid 布局
- 掌握父容器的各種屬性設定
- 靈活運用子元素的定位方式
- 建立完整的二維布局系統
CSS Grid 是現代網頁開發的重要工具,掌握它將讓您的布局能力大幅提升!
學習資源推薦
以下整理幾個優質的線上互動練習網站,幫助你輕鬆學習並實作 CSS 布局技巧。
透過遊戲方式學習 CSS Grid 布局技巧,共 28 個關卡。
透過遊戲方式學習 CSS Grid 布局技巧,共 80 個關卡。
布局技巧與選擇策略
選擇正確的布局技術是成功的關鍵。了解何時使用 FlexBox 和何時使用 Grid 是現代前端開發的重要技能。
一維布局 - 使用 FlexBox
當內容主要在一個方向上排列時使用:
one-dimension.html <style> .navbar { display: flex; justify-content: space-between; align-items: center; padding: 0 20px; background: #343a40; color: white; }
.nav-links { display: flex; list-style: none; gap: 20px; }
.button-group { display: flex; gap: 10px; margin: 20px 0; }
.btn { padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; }
.btn-primary { background: #007bff; color: white; } .btn-secondary { background: #6c757d; color: white; } </style>
<nav class="navbar"> <div class="brand">我的網站</div> <ul class="nav-links"> <li><a href="#">首頁</a></li> <li><a href="#">關於</a></li> <li><a href="#">服務</a></li> <li><a href="#">聯絡</a></li> </ul> </nav>
<div class="button-group"> <button class="btn btn-primary">主要按鈕</button> <button class="btn btn-secondary">次要按鈕</button> </div>
|
二維布局 - 使用 CSS Grid
當需要同時控制行和列時使用:
two-dimension.html<style> .dashboard { display: grid; grid-template-areas: "header header header" "sidebar main ads" "footer footer footer"; grid-template-columns: 200px 1fr 150px; grid-template-rows: 60px 1fr 40px; gap: 10px; height: 100vh; background: #f8f9fa; }
.dashboard-header { grid-area: header; background: #007bff; color: white; display: flex; align-items: center; padding: 0 20px; }
.dashboard-sidebar { grid-area: sidebar; background: #343a40; color: white; padding: 20px; }
.dashboard-main { grid-area: main; background: white; padding: 20px; border-radius: 8px; }
.dashboard-ads { grid-area: ads; background: #ffc107; padding: 10px; text-align: center; }
.dashboard-footer { grid-area: footer; background: #6c757d; color: white; display: flex; align-items: center; justify-content: center; } </style>
<div class="dashboard"> <div class="dashboard-header">控制台標題</div> <div class="dashboard-sidebar">側邊選單</div> <div class="dashboard-main">主要內容</div> <div class="dashboard-ads">廣告區</div> <div class="dashboard-footer">版權資訊</div> </div>
|
混合布局策略
在實際專案中,通常會結合使用 FlexBox 和 Grid:
hybrid-layout.html<style> .page-layout { display: grid; grid-template-rows: auto 1fr auto; min-height: 100vh; }
.page-header { background: #2c3e50; color: white; padding: 20px; display: flex; justify-content: space-between; align-items: center; }
.page-main { display: grid; grid-template-columns: 250px 1fr; gap: 20px; padding: 20px; }
.page-sidebar { background: #ecf0f1; padding: 20px; border-radius: 8px; }
.page-content { background: white; padding: 20px; border-radius: 8px; }
.page-footer { background: #34495e; color: white; padding: 20px; text-align: center; }
.article-list { display: flex; flex-direction: column; gap: 20px; }
.article-item { display: flex; gap: 15px; padding: 15px; background: #f8f9fa; border-radius: 8px; } </style>
<div class="page-layout"> <header class="page-header"> <h1>我的部落格</h1> <nav> <a href="#">首頁</a> <a href="#">文章</a> <a href="#">關於</a> </nav> </header>
<main class="page-main"> <aside class="page-sidebar"> <h3>分類</h3> <ul> <li>技術文章</li> <li>生活分享</li> <li>學習筆記</li> </ul> </aside>
<section class="page-content"> <div class="article-list"> <article class="article-item"> <img src="https://picsum.photos/100/100/?random=1" alt="文章圖片"> <div> <h3>文章標題</h3> <p>文章摘要內容。..</p> </div> </article> <article class="article-item"> <img src="https://picsum.photos/100/100/?random=2" alt="文章圖片"> <div> <h3>另一篇文章</h3> <p>文章摘要內容。..</p> </div> </article> </div> </section> </main>
<footer class="page-footer"> <p>© 2024 我的部落格。版權所有。</p> </footer> </div>
|
總結
現代 CSS 布局技術為我們提供了強大且靈活的工具:
- Float:僅用於文繞圖效果
- FlexBox:專精於一維布局
- CSS Grid:專精於二維布局
- 混合使用:在實際專案中結合使用
選擇策略總結
掌握這些技術,您就能建立出現代化、響應式且易於維護的網頁布局。記住,選擇合適的工具來解決特定的布局問題,這是成為優秀前端開發者的關鍵技能。
- ✅ 文繞圖效果
- ❌ 複雜布局(已被淘汰)
- ❌ 響應式設計
- ✅ 一維布局(行或列)
- ✅ 導航選單
- ✅ 按鈕組和表單
- ✅ 卡片布局
- ✅ 垂直/水平置中
- ✅ 二維布局(行和列)
- ✅ 整體頁面結構
- ✅ 複雜的響應式設計
- ✅ 圖片畫廊
- ✅ 儀表板布局
技術選擇決策樹
選擇正確的布局技術是成功的關鍵。以下是一個實用的決策指南:
decision-tree.html<style> .decision-tree { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; padding: 20px; background: #f8f9fa; border-radius: 8px; margin: 20px 0; }
.decision-card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); text-align: center; }
.decision-card h4 { margin-top: 0; color: #2c3e50; }
.float-card { border-top: 4px solid #e74c3c; }
.flex-card { border-top: 4px solid #3498db; }
.grid-card { border-top: 4px solid #27ae60; }
.use-case { background: #f8f9fa; padding: 10px; border-radius: 4px; margin: 10px 0; font-size: 0.9rem; }
.avoid-case { background: #fff5f5; border: 1px solid #fed7d7; padding: 10px; border-radius: 4px; margin: 10px 0; font-size: 0.9rem; color: #c53030; }
@media (max-width: 768px) { .decision-tree { grid-template-columns: 1fr; } } </style>
<div class="decision-tree"> <div class="decision-card float-card"> <h4>🌊 Float</h4> <div class="use-case"> <strong>✅ 適合:</strong><br> 文繞圖效果<br> 簡單的圖片對齊 </div> <div class="avoid-case"> <strong>❌ 避免:</strong><br> 複雜布局<br> 響應式設計<br> 垂直對齊 </div> </div>
<div class="decision-card flex-card"> <h4>📏 FlexBox</h4> <div class="use-case"> <strong>✅ 適合:</strong><br> 一維布局<br> 導航選單<br> 按鈕組<br> 卡片排列<br> 垂直/水平居中 </div> <div class="avoid-case"> <strong>❌ 避免:</strong><br> 複雜二維布局<br> 精確網格定位 </div> </div>
<div class="decision-card grid-card"> <h4>📐 CSS Grid</h4> <div class="use-case"> <strong>✅ 適合:</strong><br> 二維布局<br> 整體頁面結構<br> 複雜響應式設計<br> 圖片畫廊<br> 雜誌式布局 </div> <div class="avoid-case"> <strong>❌ 避免:</strong><br> 簡單的一維排列<br> 舊瀏覽器兼容 </div> </div> </div>
|
實際場景分析
透過具體的場景分析,我們可以更好地理解何時使用哪種布局技術。以下是三個常見的實際應用場景:
場景一:響應式導航選單
responsive-nav-analysis.html<style> .nav-comparison { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin: 20px 0; }
.nav-example { background: #f8f9fa; padding: 20px; border-radius: 8px; border: 2px solid #dee2e6; }
.nav-example h5 { margin-top: 0; text-align: center; padding: 10px; border-radius: 4px; color: white; }
.flex-nav-title { background: #3498db; }
.grid-nav-title { background: #27ae60; }
.nav-flex { display: flex; justify-content: space-between; align-items: center; background: #2c3e50; padding: 15px; border-radius: 4px; }
.nav-grid { display: grid; grid-template-columns: auto 1fr auto; align-items: center; background: #2c3e50; padding: 15px; border-radius: 4px; }
.nav-brand { color: white; font-weight: bold; }
.nav-links { display: flex; list-style: none; gap: 20px; margin: 0; padding: 0; }
.nav-links a { color: white; text-decoration: none; padding: 5px 10px; border-radius: 3px; transition: background 0.3s; }
.nav-links a:hover { background: rgba(255,255,255,0.1); }
.nav-actions { display: flex; gap: 10px; }
.nav-btn { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; font-size: 0.9rem; }
.nav-btn-primary { background: #3498db; color: white; }
.nav-grid .nav-links { justify-self: center; }
@media (max-width: 768px) { .nav-comparison { grid-template-columns: 1fr; } } </style>
<div class="nav-comparison"> <div class="nav-example"> <h5 class="flex-nav-title">FlexBox 方案</h5> <nav class="nav-flex"> <div class="nav-brand">品牌</div> <ul class="nav-links"> <li><a href="#">首頁</a></li> <li><a href="#">產品</a></li> <li><a href="#">服務</a></li> </ul> <div class="nav-actions"> <button class="nav-btn nav-btn-primary">登入</button> </div> </nav> <p><strong>適合原因:</strong>一維排列,需要彈性分配空間</p> </div>
<div class="nav-example"> <h5 class="grid-nav-title">Grid 方案</h5> <nav class="nav-grid"> <div class="nav-brand">品牌</div> <ul class="nav-links"> <li><a href="#">首頁</a></li> <li><a href="#">產品</a></li> <li><a href="#">服務</a></li> </ul> <div class="nav-actions"> <button class="nav-btn nav-btn-primary">登入</button> </div> </nav> <p><strong>適合原因:</strong>精確控制三個區域的定位</p> </div> </div>
|
場景二:產品卡片網格
product-grid-analysis.html<style> .product-comparison { margin: 20px 0; }
.product-flex { display: flex; flex-wrap: wrap; gap: 20px; padding: 20px; background: #e3f2fd; border-radius: 8px; margin: 20px 0; }
.product-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; padding: 20px; background: #f3e5f5; border-radius: 8px; margin: 20px 0; }
.product-card { background: white; border-radius: 8px; padding: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); text-align: center; }
.product-flex .product-card { flex: 1 1 250px; border-left: 4px solid #2196f3; }
.product-grid .product-card { border-left: 4px solid #9c27b0; }
.product-card h6 { margin: 0 0 10px 0; color: #2c3e50; }
.product-card p { margin: 0; color: #7f8c8d; font-size: 0.9rem; }
.analysis-box { background: #f8f9fa; padding: 15px; border-radius: 6px; margin: 10px 0; } </style>
<div class="product-comparison"> <h4>🛍️ 產品卡片布局比較</h4> <div class="analysis-box"> <strong>FlexBox 方案:</strong> <div class="product-flex"> <div class="product-card"> <h6>產品 A</h6> <p>彈性寬度,最小 250px</p> </div> <div class="product-card"> <h6>產品 B</h6> <p>自動分配剩餘空間</p> </div> <div class="product-card"> <h6>產品 C</h6> <p>適合數量不固定的情況</p> </div> </div> <p><strong>優勢:</strong>彈性分配空間,適合動態內容</p> </div>
<div class="analysis-box"> <strong>Grid 方案:</strong> <div class="product-grid"> <div class="product-card"> <h6>產品 A</h6> <p>自動填充列數</p> </div> <div class="product-card"> <h6>產品 B</h6> <p>整齊的網格對齊</p> </div> <div class="product-card"> <h6>產品 C</h6> <p>更精確的控制</p> </div> </div> <p><strong>優勢:</strong>完美的網格對齊,更好的空間利用</p> </div> </div>
|
場景三:複合布局策略
hybrid-strategy.html<style> .hybrid-demo { display: grid; grid-template-areas: "header header" "sidebar main" "footer footer"; grid-template-columns: 250px 1fr; grid-template-rows: auto 1fr auto; gap: 20px; min-height: 400px; background: #f8f9fa; padding: 20px; border-radius: 8px; }
.hybrid-header { grid-area: header; background: #2c3e50; color: white; padding: 15px; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; }
.hybrid-sidebar { grid-area: sidebar; background: #34495e; color: white; padding: 15px; border-radius: 6px; }
.hybrid-main { grid-area: main; background: white; padding: 20px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.hybrid-footer { grid-area: footer; background: #95a5a6; color: white; padding: 15px; border-radius: 6px; display: flex; justify-content: center; align-items: center; }
.content-cards { display: flex; flex-wrap: wrap; gap: 15px; margin-top: 15px; }
.content-card { flex: 1 1 200px; background: #ecf0f1; padding: 15px; border-radius: 4px; text-align: center; min-height: 100px; }
.strategy-note { background: #fff3cd; border: 1px solid #ffeaa7; padding: 15px; border-radius: 6px; margin: 20px 0; color: #856404; }
@media (max-width: 768px) { .hybrid-demo { grid-template-areas: "header" "main" "sidebar" "footer"; grid-template-columns: 1fr; } } </style>
<div class="hybrid-demo"> <header class="hybrid-header"> <h5 style="margin: 0;">混合布局示例</h5> <nav style="display: flex; gap: 15px;"> <a href="#" style="color: white;">首頁</a> <a href="#" style="color: white;">關於</a> </nav> </header>
<aside class="hybrid-sidebar"> <h6>側邊欄</h6> <p style="font-size: 0.9rem; margin: 0;">使用 Grid 精確定位</p> </aside>
<main class="hybrid-main"> <h4>主要內容</h4> <p>外層使用 Grid 控制整體布局,內層使用 FlexBox 控制卡片排列</p> <div class="content-cards"> <div class="content-card">卡片 1</div> <div class="content-card">卡片 2</div> <div class="content-card">卡片 3</div> </div> </main>
<footer class="hybrid-footer"> <p style="margin: 0;">頁尾使用 FlexBox 居中</p> </footer> </div>
<div class="strategy-note"> <strong>💡 混合策略的優勢:</strong><br> • 外層 Grid:控制整體頁面結構<br> • 內層 FlexBox:處理組件內的元素排列<br> • 充分發揮兩種技術的優勢 </div>
|
性能與兼容性考量
browser-support.html<style> .support-table { display: grid; grid-template-columns: auto repeat(4, 1fr); gap: 1px; background: #dee2e6; border-radius: 8px; overflow: hidden; margin: 20px 0; }
.support-header { background: #495057; color: white; padding: 15px; text-align: center; font-weight: bold; }
.support-cell { background: white; padding: 15px; text-align: center; }
.support-good { background: #d4edda; color: #155724; }
.support-partial { background: #fff3cd; color: #856404; }
.support-poor { background: #f8d7da; color: #721c24; }
.performance-tips { background: #e7f3ff; padding: 20px; border-radius: 8px; border-left: 4px solid #007bff; margin: 20px 0; } </style>
<div class="support-table"> <div class="support-header">技術</div> <div class="support-header">Chrome</div> <div class="support-header">Firefox</div> <div class="support-header">Safari</div> <div class="support-header">IE/Edge</div>
<div class="support-cell"><strong>Float</strong></div> <div class="support-cell support-good">✅ 全支持</div>
<div class="support-cell"><strong>FlexBox</strong></div> <div class="support-cell support-good">✅ 29+</div> <div class="support-cell support-good">✅ 28+</div> <div class="support-cell support-good">✅ 9+</div> <div class="support-cell support-partial">⚠️ IE11</div>
<div class="support-cell"><strong>Grid</strong></div> <div class="support-cell support-good">✅ 57+</div> <div class="support-cell support-good">✅ 52+</div> <div class="support-cell support-good">✅ 10.1+</div> <div class="support-cell support-partial">⚠️ IE11</div> </div>
<div class="performance-tips"> <h4>🚀 性能優化建議</h4> <ul> <li><strong>避免深層嵌套</strong>:過多的 Grid 或 Flex 容器會影響性能</li> <li><strong>合理使用 gap</strong>:相比 margin,gap 屬性更高效</li> <li><strong>善用 CSS 硬件加速</strong>:transform 和 opacity 動畫性能更好</li> <li><strong>測試實際設備</strong>:不同設備的性能差異很大</li> </ul> </div>
|
實戰決策流程
decision-flowchart.html<style> .flowchart { display: flex; flex-direction: column; gap: 20px; padding: 20px; background: #f8f9fa; border-radius: 8px; margin: 20px 0; }
.flow-step { display: grid; grid-template-columns: 200px 1fr; gap: 20px; align-items: center; background: white; padding: 20px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.flow-question { background: #e3f2fd; padding: 15px; border-radius: 6px; text-align: center; font-weight: bold; color: #1565c0; }
.flow-answer { display: flex; flex-direction: column; gap: 10px; }
.flow-option { padding: 10px; border-radius: 4px; border: 2px solid #dee2e6; cursor: pointer; transition: all 0.3s; }
.flow-option:hover { border-color: #007bff; background: #f8f9fa; }
.flow-option.float { border-color: #e74c3c; }
.flow-option.flex { border-color: #3498db; }
.flow-option.grid { border-color: #27ae60; }
.final-recommendation { background: #d4edda; border: 2px solid #c3e6cb; padding: 20px; border-radius: 8px; margin: 20px 0; text-align: center; } </style>
<div class="flowchart"> <div class="flow-step"> <div class="flow-question">需要文繞圖效果?</div> <div class="flow-answer"> <div class="flow-option float"> <strong>是</strong> → 使用 Float<br> <small>Float 專門用於文繞圖</small> </div> <div class="flow-option"> <strong>否</strong> → 繼續下一步 </div> </div> </div>
<div class="flow-step"> <div class="flow-question">需要二維布局控制?</div> <div class="flow-answer"> <div class="flow-option grid"> <strong>是</strong> → 使用 CSS Grid<br> <small>同時控制行和列</small> </div> <div class="flow-option"> <strong>否</strong> → 繼續下一步 </div> </div> </div>
<div class="flow-step"> <div class="flow-question">需要彈性空間分配?</div> <div class="flow-answer"> <div class="flow-option flex"> <strong>是</strong> → 使用 FlexBox<br> <small>一維彈性布局</small> </div> <div class="flow-option"> <strong>否</strong> → 考慮傳統方法 </div> </div> </div> </div>
<div class="final-recommendation"> <h4>🎯 最終建議</h4> <p>在現代網頁開發中,<strong>80%</strong> 的情況下會使用 <strong>FlexBox</strong> 和 <strong>Grid</strong> 的組合。<br> Float 僅保留用於文繞圖等特殊效果。</p> </div>
|
布局技術選擇的黃金法則
- Float:只用於文繞圖,避免用於布局
- FlexBox:一維布局的首選,特別適合組件內部
- Grid:二維布局的王者,適合整體頁面結構
- 組合使用:發揮各自優勢,創造完美布局
- 響應式優先:選擇天然支持響應式的技術