1 基礎
盡可能使用瀏覽器的版面配置引擎,以提升效能。在採用硬式編碼尺寸或複雜的媒體查詢之前,請先嘗試使用內建大小、邏輯屬性和 aspect-ratio。
1.1 該使用哪種版面配置模式?
從上到下瀏覽決策樹狀圖,並在第一個相符項目處停止。請注意,版面配置可以相互巢狀,且每項決策都是根據該容器的用途而定。
- 是否為簡單的項目列或欄?使用 Flexbox:1D、內容優先、內容沿著單一軸線分布。
- 巢狀元素是否需要與其祖項格線的軌道對齊?使用 subgrid:2D、關係優先、繼承父項軌道,讓孫項能與同層級元素對齊。
- 頁面或元件結構是否複雜,同時包含列和欄?使用格線:2D、版面配置優先,您定義骨架,內容則填滿骨架。
- 內容是否為長篇散文,應拆分為平衡的欄?使用多欄:一維流程,報紙樣式。
- 是否需要緊密包裝高度不一的商品?目前請搭配
grid-auto-flow: dense使用 grid;只有在原生磚牆 (又稱「格線通道」) 推出基準目標時,才使用原生磚牆 (請參閱 §8)。 - 元素是否需要浮動在頁面上方,並在空間上與觸發條件保持連結,即使跨越 DOM 邊界或堆疊內容也一樣?使用錨定定位:在觸發條件上使用
anchor-name,在疊加層上使用position-anchor(請參閱第 5 節)。
1.2 運作原理
- 使用邏輯屬性 (
inline-size、block-size、margin-inline、padding-block、inset-inline-start) 設定版面配置尺寸和間距,詳情請參閱「CSS:現代架構」。 - 套用內容優先與版面配置優先的心智模型:當項目決定流程時,使用彈性方塊;當你先定義骨架時,使用格線。
- 使用
place-*簡寫 (place-content、place-items、place-self),在一個宣告中對齊兩個軸。 - 先使用內建大小 (
min-content、max-content、fit-content()) 和彈性軌道 (fr、minmax()),再使用固定的width/height,這樣就能減少媒體查詢,並提高版面配置的彈性。 - 請勿使用
overflow: hidden遮蓋版面配置問題,請從來源修正。舉例來說,某些替換元素 (例如<canvas>、<img>、<svg>、<video>、<iframe>) 預設會使用display: inline,這可能會在某些版面配置中加入間隙。請勿使用overflow裁剪間隙,而是套用區塊 display-outside 值 (例如display: block、grid、flex等) 來移除間隙。 - 使用
aspect-ratio為媒體預留空間,避免素材資源載入前版面配置位移。
.sidebar { inline-size: max-content; } /* Size to longest unbreakable token. */
.main-content { inline-size: fit-content; } /* Grow to available space, no further. */
.media { aspect-ratio: 16 / 9; inline-size: 100%; block-size: auto; }
body.centered { display: grid; place-content: center; min-block-size: 100dvb; }
如要瞭解
calc-size()和受限的固有大小,請參閱「使用固有大小計算」。
2 Flexbox
一維版面配置:項目會沿著單一主軸排列,並在交錯軸上對齊。適用於導覽列、工具列、項目列,以及任何單列或單欄分布。
建議做法:
- 使用
display: flex建立情境,並使用flex-direction設定主軸 (預設為row)。 - 只要有可能溢位,請使用
flex-wrap: wrap。如果nowrap沒有overflow: auto/hidden,就會溢出到窄檢視區。 - 在精簡項目 (例如熱門標籤集、篩選器、按鈕群組或導覽連結) 的換行資料列上,在
flex-wrap: wrap後方加上flex-wrap: balance,即可在各行平均分配項目,避免最後一行出現單一孤立項目;不支援的瀏覽器會改用wrap。 - 在項目上使用
flex簡寫<grow> <shrink> <basis>(例如flex: 1 1 250px),而不是個別設定flex-grow/flex-shrink/flex-basis。 - 請使用
gap(或row-gap/column-gap長寫) 設定項目之間的間距,而非子項邊界。 - 在位置對齊方式前加上
safe(例如align-items: safe center),這樣當容器比內容窄時,可聚焦內容就不會遭到裁剪。 - 使用
margin-inline-start: auto(或margin-block-start: auto) 將單一項目推到主軸的最末端,這是標準的跳脫機制。 - 使用
align-self覆寫每個項目的交錯軸對齊設定。 - 使用
align-items將所有項目置中於交叉軸;在單一項目上使用margin: auto,將其置中於兩個軸;僅在容器換行且各列之間有額外空間時,才使用align-content。 - 在包含長度過長且無法中斷內容 (網址、程式碼、長字串) 的彈性項目上設定
min-inline-size: 0(或min-width: 0) - 根據預設,彈性項目不會縮小到小於內容大小,導致溢位。
請勿:
- 請勿在彈性項目上使用
justify-self,因為這項屬性僅適用於格線、區塊和絕對定位版面配置。請改用自動邊界。 - 請勿使用
order或flex-direction: *-reverse重新排序互動式內容。這些屬性只會變更視覺順序,DOM 順序仍會決定焦點順序,因此鍵盤分頁流程與使用者看到的內容不符。 - 請勿混淆
space-around(兩端間距為一半) 和space-evenly(前後和中間間距相等)。 - 別忘了軸線會翻轉:當
flex-direction: column時,justify-content會對齊區塊軸,align-items則會對齊內嵌軸,與預設值相反。 - 請勿將容器和子項的大小設為填滿彼此,這是造成溢位和非預期結果的常見原因。為其中一邊指定明確大小。
- 請勿在同一個項目上同時設定
flex-basis和width/inline-size,因為在彈性內容中,flex-basis優先順序較高,系統會忽略width。使用flex-basis(或flex簡寫) 做為調整彈性項目大小的單一事實來源。
.card-grid { display: flex; flex-flow: row wrap; gap: 1rem; }
.card-item { flex: 1 1 250px; } /* grow, shrink, basis */
.card-item-action { margin-inline-start: auto; } /* Push to main-axis end. */
.toolbar { display: flex; align-items: safe center; }
.tag-list { display: flex; flex-wrap: wrap; flex-wrap: balance; gap: 0.5rem; }
3 格線和子格線
二維版面配置:明確定義列和欄,或讓引擎衍生。子格線可讓巢狀格線沿用父項的軌跡,讓孫項與同層級項目對齊。
選擇格線功能:
- 您是否知道確切需要的欄數?
- 是:使用明確版本 (
grid-template-columns: 200px 1fr、repeat(3, 1fr)等) - 不同資料欄是否需要不同大小 (側欄 + 主欄、橫跨所有欄的標頭)?→ 使用
grid-template-areas命名可讀取的區域 - 所有資料欄是否都一致,或純粹依行號定位?→ 使用
repeat(N, ...)或命名線 - 否 (回應式,項目數量不明) - 使用
repeat(auto-fit, minmax(min, 1fr)) - 最後一列的項目是否應延伸,直到填滿剩餘空間?→
auto-fit - 空白的最後一列軌道是否應保持最小尺寸 (保留欄幽靈版位)?→
auto-fill
- 是:使用明確版本 (
- 需要將物品放在特定位置嗎?
- 是:使用
grid-column: <start> / <end>或grid-area: <name> - 否 (僅跨越多個軌道,流程位置不重要) — 使用
grid-column: span <n>
- 是:使用
- 子項元素是否需要沿用父項格線的軌道大小 (同層元素之間不規則對齊)?
- 是:在受影響的軸上使用子格線
- 每個儲存格的子項數量是否可變?→ 僅一個軸使用 subgrid,另一個軸使用
grid-auto-rows/grid-auto-columns - 子項數量是否固定?→ 兩個軸上都有子格線
- 否:標準格線,不需要子格線
建議做法:
- 使用
display: grid建立情境。 grid-template-areas適用於複雜的頁面層級版面配置,區域名稱可自我記錄,且宣告可對齊列和欄,一目瞭然。- 使用
repeat(auto-fit, minmax(200px, 1fr))建立回應式資訊卡格線,將填滿的軌道拉伸至填滿整列,或使用auto-fill將空白重複軌道保留在最小大小。 - 使用
fr進行比例軌道分配,並使用minmax(min, max)進行彈性但有界限的軌道。 - 使用
grid-column: span <n>調整項目在軌道上的大小、使用grid-column: <start> / <end>將項目放在特定線條上,或使用grid-area: <name>將項目放在命名區域。 - 使用子格線 (
grid-template-columns: subgrid或grid-template-rows: subgrid) 解決資訊卡清單中的「不規則邊緣」問題,讓標題、中繼資料和行動號召等內部元素在同層級元素之間對齊。 - 將子格線宣告與前方的明確
grid-template-rows/-columns宣告配對,做為舊版瀏覽器的相同階層備用方案。
請勿:
- 請勿預期
auto-fit/auto-fill軌道大小來自項目內容,而是來自repeat()大小引數。 - 請勿在互動式內容上使用
grid-auto-flow: dense。雖然能有效率地排列項目,但會重新排序視覺效果,破壞 DOM 順序的鍵盤分頁流程。 - 如果子項數量不固定,請勿將子格線套用至兩條軸。額外項目會放在最後一個軌道,請改用
grid-auto-rows/grid-auto-columns做為隱含軸。 - 請勿混淆
justify-items/align-items(對齊軌道內的項目內容) 和justify-content/align-content(對齊容器內的格線軌道)。如果使用錯誤的屬性,系統不會顯示任何訊息,也不會產生任何效果。 - 請勿在容器上使用
repeat(auto-fit/auto-fill, ...),而不指定明確的inline-size。在display: inline-grid或未指定大小的彈性項目中,容器沒有可分割的寬度,因此無法預測軌道數量。
3.1 程式碼範例:格線和子格線
頁面殼層:<main class="page-layout"> 包含 <header>、<aside>、含有 <div class="card"> 個子項的 <section class="card-grid">,以及 <footer>。
/* Align grid-template-areas in rows and columns for readability. */
.page-layout {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
gap: 1.5rem;
}
header { grid-area: header; }
aside { grid-area: sidebar; }
footer { grid-area: footer; }
.card-grid {
grid-area: main;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
grid-template-rows: auto 1fr; /* title block, body block */
gap: 1rem;
}
.card {
grid-row: span 2;
display: grid;
/* Same-cascade fallback: ignored when subgrid is supported. */
grid-template-rows: auto 1fr;
grid-template-rows: subgrid;
}
4 容器查詢
查詢祖系容器的大小 (或計算樣式),而非可視區域。心智模型:容器查詢 = 元件情境;媒體查詢 = 全域頁面版面配置和使用者偏好設定 (prefers-color-scheme、prefers-reduced-motion)。
建議做法:
- 在包裝函式上使用
container-type: inline-size(僅限寬度查詢) 或container-type: size(兩個軸) 建立容器環境,然後才能查詢其子系。 - 如果巢狀結構定義可能發生衝突,請使用
container-name(或container簡寫:container: card / inline-size) 為容器命名。 - 計算流體類型和間距時,納入容器查詢單位:
cqi/cqb(邏輯內嵌/區塊)、cqw/cqh(實體)、cqmin/cqmax。 - 只要使用
container-type: size,就必須為容器指定明確的block-size,否則子系會收合,因為大小限制會強制容器忽略其內容。
請勿:
- 請勿使用
block-size做為container-type值,因為這不是有效值。兩個軸都使用size。 - 宣告
container-type後,請勿預期子項的固有大小會影響容器。容器啟用後,系統會將容器視為沒有子項。 - 請勿在不符合條件的祖系後代中使用容器查詢單位,因為這些單位會改用小型可視區域 (
svw/svh)。
4.1 程式碼範例:使用容器查詢單位的流動字體排版
.card-wrapper {
container: card / inline-size; /* shorthand for container-name / container-type */
}
@container card (inline-size > 400px) {
.content {
display: flex;
gap: 2rem;
}
}
.title {
/* Fluid type bound to the container width, not the viewport. */
font-size: clamp(1rem, 4cqi, 2rem);
}
5 原生重疊、錨定定位和堆疊情境
各疊加層基元的適用時機:
- 使用
popover建立暫時性、非互動式的 UI (彈出式視窗、浮動式訊息、工具提示),這類 UI 位於頂層,不需要z-index管理。 - 將
<dialog>與.showModal()搭配使用,可進行需要焦點捕捉和惰性背景的互動。 - 請勿在同一個元素上合併
popover和.showModal(),因為這兩者是互斥的執行階段狀態。
錨定定位 (疊加層的空間版面配置):
- 使用
position-area(或anchor()內嵌) 和anchor-size(),根據觸發條件設定疊加層的位置和大小。 - 使用
position-try-fallbacks: flip-block(或flip-inline),讓瀏覽器在疊加層超出可視區域時重新定位。 - 請勿在單一
position-area值中混用實體和邏輯關鍵字,請選擇其中一種座標系統。 - 使用
@supports (anchor-name: --x)偵測功能,並提供絕對位置備用方案。
如需完整的實作詳細資料、polyfill 策略和
popover值參考資料,請參閱「宣告式對話方塊和彈出式視窗控制項」和「位置感知工具提示」。如要瞭解如何將錨定定位套用至下拉式選單、彈出式選單和分頁指標,請參閱「Viewport-Aware Dropdowns」和「Anchor Positioning Tab Underline」。
6 溢位追蹤和版面配置穩定性
以可預測的方式管理版面配置位移、捲軸和裁剪。
建議做法:
- 使用
overflow: auto,只有在內容實際溢出時,才會顯示捲軸。 - 使用
overflow: clip裁剪內容,不建立捲動容器;使用overflow-clip-margin啟用溢出功能。 - 使用
scrollbar-gutter: stable為捲軸保留空間,並在內容增加時防止版面配置位移。 - 在巢狀捲動區域 (例如側欄、互動視窗和清單) 使用
overscroll-behavior: contain(或none),防止捲動鏈結向上傳遞至頁面,或在中間捲動包裝函式 (例如滑動顯示軌跡) 使用overscroll-behavior: chain,以便將多餘的捲動傳遞至祖系捲動器,而不會觸發本機橡皮筋彈跳。 使用
-webkit-line-clamp+display: -webkit-box+-webkit-box-orient: vertical三元組進行多行截斷,儘管有前置字元,但這個模式已完整指定,且未淘汰。請一併宣告不含前置字元的line-clamp簡寫;尚未支援該屬性的瀏覽器會忽略該屬性,不會造成任何影響。請勿:如果
auto就能解決問題,請勿使用overflow: scroll,因為scroll會強制顯示捲軸,即使沒有可捲動的內容也一樣。如果只想裁剪,請勿使用
overflow: hidden,因為hidden會建立可透過程式輔助捲動的捲動容器。
.scrollable-list {
max-block-size: 400px;
overflow-y: auto;
scrollbar-gutter: stable; /* Reserve scrollbar space. */
overscroll-behavior: contain; /* No scroll chaining into the page. */
}
.snippet {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
line-clamp: 3; /* Ignored where unsupported. */
overflow: clip;
}
如要深入瞭解
overflow: clip和overflow-clip-margin,請參閱「溢位裁剪控制項」。如要在滑動顯示 UI 中使用overscroll-behavior: chain進行巢狀捲動交接,請參閱「滑動顯示」。如要瞭解捲軸顏色、大小和主題,請參閱「自訂捲軸的顏色或粗細」、「深色模式」和「根據高對比偏好設定調整捲軸」。
7 檢視區機制和追蹤分布
- 如果行動版版面配置容器必須考量瀏覽器 UI 移位 (網址列收合/展開),請使用
dvh/dvw。 - 請勿使用
100vw設定全寬版面配置,因為這會忽略捲軸寬度,導致水平溢位。請改用100%、100dvw或100svw。
如需回應式設計的進入點 (動態可視區域單位、保留媒體空間、流動字體排版),請參閱「回應式設計」。
8 格線道 (又稱拼磚)
這項規格目前以「格線車道」為名開發中 (例如 display: grid-lanes),而先前的實驗原型則使用 grid-template-rows: masonry。
建議做法:
- 立即使用格線搭配
grid-auto-flow: dense進行緊密排列,並接受 DOM 順序可能與視覺順序不符。 - 如果項目是文件片段,而非權重相同的資訊卡,請使用多欄 (
columns: 3; column-gap: 1rem) 呈現內容豐富的磚石樣式流程。 - 請將
grid-template-rows: masonry視為漸進增強功能,並使用@supports偵測功能。
請勿:
- 在基準目標趕上之前,請勿將
grid-template-rows: masonry設為硬性規定。
.gallery { columns: 3 200px; column-gap: 1rem; }
.gallery > * { break-inside: avoid; margin-block-end: 1rem; }
@supports (grid-template-rows: masonry) {
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-template-rows: masonry;
gap: 1rem;
columns: unset;
}
}