flex 佈局用了這麼多年,justify-content 和 align-items 還是有人老是記混。不是因爲笨,是因爲這兩個屬性的行爲會隨 flex-direction 變化,記住"橫向縱向"沒用,下次換了方向又亂了。
這篇文章從主軸和交叉軸的概念出發,講清楚爲什麼記混、怎麼記對,以及幾個常見場景的寫法。
先搞清楚一件事:軸的方向不是固定的
很多人背的是"justify-content 控制水平方向,align-items 控制垂直方向"。這句話在默認情況下是對的,但只要 flex-direction 改了,這句話就錯了。
準確的描述是:
justify-content:控制主軸方向的對齊align-items:控制交叉軸方向的對齊
主軸是什麼?就是 flex-direction 指定的方向:
flex-direction: row; /* 主軸是水平方向(默認) */
flex-direction: row-reverse; /* 主軸是水平方向,但從右往左 */
flex-direction: column; /* 主軸是垂直方向 */
flex-direction: column-reverse; /* 主軸是垂直方向,但從下往上 */
交叉軸永遠和主軸垂直。主軸是水平的,交叉軸就是垂直的;主軸是垂直的,交叉軸就是水平的。
所以當你把 flex-direction 改成 column,兩個屬性的效果就完全反過來了:
/* flex-direction: row(默認) */
.container {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
/* flex-direction: column */
.container {
display: flex;
flex-direction: column;
justify-content: center; /* 垂直居中! */
align-items: center; /* 水平居中! */
}
記這個最簡單的方式:justify 跟着主軸走,align 跟着交叉軸走,主軸在哪 justify 就控制哪個方向。
垂直居中,爲什麼有時候不生效?
這是最常見的問題。寫了 align-items: center,元素就是不居中。
原因幾乎只有一個:容器沒有高度,或者高度不夠。
align-items 控制的是元素在交叉軸上的位置,但如果容器本身沒有指定高度,它的高度就等於子元素的高度,根本沒有多餘的空間,居中也就無從談起。
/* 不生效:容器高度就是內容高度,沒有空間居中 */
.container {
display: flex;
align-items: center;
}
/* 生效:給容器一個高度 */
.container {
display: flex;
align-items: center;
height: 300px; /* 或者 min-height,或者 100vh */
}
做全屏垂直居中:
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
space-between、space-around、space-evenly 有什麼區別?
這三個值都是 justify-content 的選項,都是把剩餘空間分配給間距,但分配方式不同。
假設容器裏有三個元素,用示意圖來看:
space-between: |A B C| 首尾元素貼邊,間距在中間平均分
space-around: | A B C | 每個元素兩側各有等量空間(首尾是內部間距的一半)
space-evenly: | A B C | 所有間距完全相等,包括首尾
實際寫代碼時:
/* 導航欄:logo 在左,鏈接在右 */
.nav {
display: flex;
justify-content: space-between;
}
/* 卡片列表:卡片之間和兩側都有間距 */
.cards {
display: flex;
justify-content: space-evenly;
}
不過現在更推薦直接用 gap 來控制間距,而不是依賴 justify-content 的 space 系列值,因爲 gap 更直觀,而且在換行時行爲也更符合預期:
.container {
display: flex;
flex-wrap: wrap;
gap: 16px; /* 元素之間的間距,首尾不加 */
}
align-items 和 align-content 的區別
這也是常見的困惑點。
align-items:控制每一行內部,子元素在交叉軸上的對齊方式align-content:控制多行在容器交叉軸上整體的分佈方式,只有在flex-wrap: wrap且實際發生了換行時纔有效果
/* 只有一行內容時,align-content 沒有效果 */
.container {
display: flex;
align-items: center; /* 這行有效:控制行內對齊 */
align-content: center; /* 這行無效:只有一行,沒有多行分佈可言 */
}
/* 多行時,兩個屬性同時發揮作用 */
.container {
display: flex;
flex-wrap: wrap;
height: 400px;
align-items: flex-start; /* 每行內部:頂部對齊 */
align-content: space-between; /* 多行之間:兩端對齊 */
}
記憶方式:items 管的是行內的事,content 管的是行與行之間的事。
幾個常見佈局的寫法
水平垂直居中(最常用)
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
導航欄:左邊 logo,右邊按鈕
.nav {
display: flex;
justify-content: space-between;
align-items: center;
}
把最後一個元素推到最右邊
.nav {
display: flex;
align-items: center;
}
.nav .last-item {
margin-left: auto; /* auto margin 會吃掉所有剩餘空間 */
}
等高卡片列表
.cards {
display: flex;
flex-wrap: wrap;
gap: 16px;
align-items: stretch; /* 默認值,子元素自動拉伸到等高 */
}
豎向排列,水平居中
.container {
display: flex;
flex-direction: column;
align-items: center; /* 注意:column 時,align-items 控制水平方向 */
}
想直接驗證這些佈局效果,把 HTML 和 CSS 粘到 HTML 在線編輯器 裏實時預覽,改一個屬性馬上看到變化,比在本地建文件測試快多了。



加載中...