
內容摘要
只要置中一個元素,用 Grid 的 place-items: center 最短也最正確;父層有好幾個子元素時用 Flexbox;內容溢出時則是靠 margin: auto 救回來。
CSS 置中為什麼老是做不對?因為正確答案取決於父層,也因為 CSS 後來長出了三種都很好用的做法。這篇先給短答案,再依情境給方法,最後說明那些「在這裡可行、換個版面就默默失效」的陷阱。
文中每個範例都能在 UrsaKit 的 CSS 網上編輯器 上貼上就看到結果。
01短答案
/* 單一元素、兩個軸向,父層有高度 */
.parent {
display: grid;
place-items: center;
}
/* 多個子元素,單軸或雙軸 */
.parent {
display: flex;
justify-content: center;
align-items: center;
}
/* 有寬度的區塊,只做水平置中 */
.child {
width: min(100%, 40rem);
margin-inline: auto;
}
這三種涵蓋了絕大多數情況。接下來解釋每一種各自依賴什麼。
02Flexbox:預設答案
Flexbox 沿著一個軸向分配剩餘空間,並在另一個軸向對齊項目。
.parent {
display: flex;
justify-content: center; /* 主軸:預設是水平 */
align-items: center; /* 交叉軸:預設是垂直 */
min-height: 100vh;
}
兩個細節決定它會不會成功:
- 主軸跟著
flex-direction走。 當flex-direction: column時,justify-content控制垂直、align-items控制水平。把這兩個屬性讀成「水平」與「垂直」,正是置中看起來壞掉的原因。 - 容器必須有多餘空間。
align-items: center分配的是子元素用完之後剩下的高度。如果父層高度等於內容高度,就沒有東西可分配,元素會留在原位。
想把整組內容一起置中,用
place-content: center。
justify-content與align-content決定的是 flex 或 grid 容器裡「行」的位置。如果多個子元素應該聚在一起置中、而不是分散開來,就設place-content: center,並讓align-items保持預設值。
03Grid:兩行解決兩個軸向
Grid 可以在完全不知道子元素大小的情況下,把它在兩個軸向置中。
.parent {
display: grid;
place-items: center;
min-height: 100vh;
}
place-items: center 是 align-items: center 與 justify-items: center 的簡寫。它能成立,是因為子元素佔的是自己的 grid 區域,而不是共用的 flex 行。
這個簡寫以 Grid 為先。在 Flexbox 裡 justify-items 不生效,因為主軸上的項目是整組處理,所以 place-items 的第二個值會被忽略。
與 Flexbox 的實際差異,在多個子元素時最明顯:
| 版面 | Flexbox | Grid |
|---|---|---|
| 單一子元素置中 | 可行 | 最短 |
| 子元素排成一列、整組置中 | justify-content: center | place-content: center |
| 每個子元素在各自格子裡置中 | 麻煩 | place-items: center |
| 等高的欄位 | 要注意 align-items: stretch | 原生支援 |
04margin: auto
對於寬度小於容器的區塊元素,auto 外距會分配剩下的空間:
.child {
width: min(100%, 40rem);
margin-inline: auto;
}
讓人意外的是垂直版本。在一般區塊版面中,垂直的 auto 外距會計算為 0,所以 margin: auto 無法把區塊垂直置中:
/* 不會垂直置中:父層不是 flex 或 grid 容器 */
.parent {
height: 100vh;
}
.child {
margin: auto;
}
/* 會垂直置中:子元素現在是 flex 項目 */
.parent {
display: flex;
height: 100vh;
}
.child {
margin: auto;
}
這不只是冷知識。項目上的 margin: auto 正是下面那個溢出問題的標準解法。
05無法控制父層時,用絕對定位
如果父層必須維持普通區塊——canvas 外框、簡報、第三方函數庫渲染出來的標記——就把元素移出文件流:
.parent {
position: relative;
}
.overlay {
position: absolute;
inset: 0;
margin: auto;
width: 200px;
height: 100px;
}
inset: 0 搭配 margin: auto 可以在不知道父層尺寸的情況下,置中一個固定大小的盒子。尺寸未知時,則改用 transform 版本:
.overlay {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
transform 做法會讓元素不再參與父層版面,所以它適合當備援,而不是預設做法。
06文字與行內內容
行內內容靠父層的 text-align 置中,而垂直置中是另一個問題:
.title {
text-align: center;
}
.badge {
display: grid;
place-items: center;
min-height: 2.5rem;
}
/* 舊式單行技巧:只對單行有效 */
.button {
line-height: 2.5rem;
height: 2.5rem;
}
line-height 置中在文字折成兩行的瞬間就破功,因為行框仍是一行的高度,內容卻長大了。優先用元素自己的 flex 或 grid。
07每種做法會失效的情況
| 做法 | 失效時機 | 修正 |
|---|---|---|
| Flexbox,雙軸置中 | 容器沒有多餘高度 | 加 min-height 或給父層高度 |
| Flexbox,雙軸置中 | 置中的子元素比容器大 | 在項目上用 margin: auto,或用 justify-content: safe center |
flex-direction: column 下的 justify-content | 軸向期待被對調 | 水平軸改用 align-items |
margin: auto | 父層是一般區塊版面 | 把父層改成 flex 或 grid |
margin-inline: auto | 元素是 width: 100% | 設定最大寬度,例如 max-width: 40rem |
| 絕對定位加 transform | 父層沒有定位 | 在父層設 position: relative |
line-height 置中 | 文字換行 | 改用 grid 或 flex |
置中的 flex 元素可能把自己的上緣藏起來。
當內容比容器高、又套用了
justify-content: center(或align-items: center),溢出部分會延伸到滾動原點之上,開頭幾行就再也捲不到。在項目上加上margin: auto、或改用safe center,就能讓內容開頭保持可滾動。
08除錯置中問題的順序
- 先看父層高度 — 在開發者工具的版面面板選取父層。如果它的高度等於內容高度,垂直置中就沒有材料可用。
- 確認父層用哪個軸向 —
flex-direction: row表示justify-content是水平。改成 column 卻沒改屬性,是「突然不置中了」最常見的原因。 - 找找有沒有 width: 100% — 已經填滿容器的元素沒有剩餘空間,auto 外距自然沒作用。
- 用真實內容測試,而不是空狀態 — 先用實際文字置中,再用溢出的文字測一次,在 CSS 網上編輯器 上做。多數置中 bug 只在內容變大時才出現。
要把這件事做對,關鍵多半在於搞清楚「剩餘空間屬於哪個元素」。這一點清楚之後,屬性名稱就不再神祕了。
09資料來源
- MDN — Aligning items in a flex container:剩餘空間、主軸與交叉軸(取用日期:2026-10-09)
- MDN — justify-content:主軸分配與 safe 關鍵字(取用日期:2026-10-09)
- MDN — align-items:交叉軸對齊(取用日期:2026-10-09)
- MDN — place-items:簡寫,以及 Flexbox 為何忽略 justify-items(取用日期:2026-10-09)
- MDN — margin:auto 外距與置中(取用日期:2026-10-09)
- W3C — CSS 2.1 視覺格式化模型:區塊軸上的 auto 外距計算為 0(取用日期:2026-10-09)
- MDN — inset:用 auto 外距定位固定大小的盒子(取用日期:2026-10-09)
- MDN — line-height:行框高度與換行(取用日期:2026-10-09)
- MDN — text-align:行內內容對齊(取用日期:2026-10-09)
- W3C — CSS Box Alignment Module Level 3:safe 與 unsafe 溢出對齊(取用日期:2026-10-09)
- W3C — CSS Transforms Module Level 1:transform 與版面(取用日期:2026-10-09)
對著即時標記編輯 CSS,邊打字邊看版面變化。
CSS 網上編輯器常見問題
只置中一個元素,最短的寫法是什麼?
把父層設為 grid 容器並加上 place-items: center。元素會在水平與垂直方向同時置中,而且父層不需要知道子元素的大小。
為什麼 align-items: center 完全沒作用?
因為父層沒有多餘的高度可以分配。垂直置中需要父層有明確高度、min-height,或是一條被拉伸的 flex/grid 軸線。
為什麼 margin: auto 只能水平置中?
在一般區塊版面中,auto 外距只會分配行內方向剩下的空間。要靠 auto 外距垂直置中,元素必須是 flex 或 grid 項目,因為那時區塊軸也會分配剩餘空間。
為什麼置中的 flex 元素捲不到最上面?
當 flex 項目比容器大、又套用了 justify-content: center 時,溢出部分會跑到滾動原點之上。改在項目上使用 margin: auto,或用 safe center,就能保住起始端。
place-items 只能用在 Grid 嗎?
place-items 是 align-items 與 justify-items 的簡寫,兩者在 Grid 可用,在 Flexbox 只有部分生效。Flexbox 裡 justify-items 沒有作用,因為 flex 項目是由 justify-content 分配。
還需要用絕對定位加 transform 嗎?
只有在父層沒辦法變成 flex 或 grid 容器時才用,例如父層由第三方函數庫控制,或元素必須疊在 canvas 之上。
相關文章
- HTML 文件結構完整說明
先確認你要置中的標記真的如你所想。
- 壓縮圖片又不犧牲可見畫質
為什麼元素上的 width 與 height 仍然影響版面。
相關工具
- CSS 網上編輯器
對即時標記測試每種置中做法。
- HTML 網上工具
先建出 CSS 要處理的標記。
- JavaScript 網上執行器
量測版面改動後的結果。
- Diff 文字比對
重構前後比對兩份樣式表。