动态

详情 返回 返回

Flex 佈局實戰指南:從踩坑到精通,解決 90% 佈局難題 - 动态 详情

前言:你是否也被這些 Flex 問題折磨過?

“為什麼我用justify-content: center卻無法垂直居中?”

align-itemsalign-content到底什麼時候生效?”

“設置了width: 200px,加了flex:1後怎麼沒用了?”

作為前端開發最常用的佈局方案,Flex(彈性佈局)以 “靈活” 著稱,但這份靈活也讓很多開發者陷入 “混亂”—— 核心原因是沒吃透 “主軸與交叉軸” 的邏輯,以及各屬性的適用場景。本文將從基礎概念到實戰案例,帶你徹底搞懂 Flex 佈局,從此告別 “試錯式調樣式”。

一、Flex 佈局基礎:先搞懂這兩個核心概念

在學習任何屬性前,必須先理清 Flex 佈局的 “骨架”——父元素(flex container)子元素(flex item) 的關係,以及最關鍵的主軸與交叉軸

1.1 什麼是 Flex 佈局?

Flex(Flexible Box)即 “彈性佈局”,通過給父元素設置display: flex,讓其所有子元素自動成為 “彈性子元素”,從而實現靈活的排列、對齊和尺寸分配。

一句話總結:父元素控制 “整體排列規則”,子元素控制 “自身特殊表現”。

/\* 最簡單的Flex佈局示例 \*/

.parent {

        display: flex; /\* 父元素開啓Flex佈局 \*/

        width: 500px;

        height: 300px;

        background: #f5f5f5;

}

.child {

        width: 100px;

        height: 100px;

        background: #42b983;

        margin: 10px;

}

效果:3 個child會自動沿水平方向排列(默認主軸方向),無需浮動或定位。

1.2 主軸與交叉軸:Flex 佈局的 “座標系”

這是最容易混淆的點!記住:所有 Flex 屬性都基於 “主軸” 和 “交叉軸”,而非固定的 “水平 / 垂直方向”

  • 主軸(main axis):子元素的排列方向,由flex-direction決定(默認水平向左)。
  • 交叉軸(cross axis):與主軸垂直的方向(默認垂直向下)。

舉個例子:當flex-direction: column(主軸設為垂直)時,原來的 “水平軸” 變成交叉軸,“垂直軸” 變成主軸 —— 此時justify-content(主軸對齊)控制垂直方向,align-items(交叉軸對齊)控制水平方向,這也是很多人 “垂直居中失效” 的根源!

核心口訣:先看flex-direction定主軸,再用對應屬性調對齊。

二、父元素的 6 個核心屬性:控制整體佈局

父元素的屬性決定了子元素的 “排列規則”,6 個屬性覆蓋 “方向、換行、對齊” 三大需求,每個屬性都有明確的適用場景。

2.1 flex-direction:決定主軸方向(子元素排列方向)

作用:定義主軸的方向,直接影響子元素的排列方向。

取值與效果

取值 主軸方向 子元素排列效果 適用場景
row(默認) 水平向左 從左到右排列 導航欄、水平列表
row-reverse 水平向右 從右到左排列 反向導航、特殊排版
column 垂直向上 從上到下排列 表單、垂直列表、卡片組
column-reverse 垂直向下 從下到上排列 特殊垂直佈局(極少用)

代碼演示(row vs column)

/\* 1. 水平排列(row):導航欄場景 \*/

.nav {

        display: flex;

        flex-direction: row; /\* 默認,可省略 \*/

        justify-content: space-between; /\* 兩端對齊 \*/

        padding: 0 20px;

        background: #fff;

}

.nav-item {

        padding: 10px;

}

/\* 2. 垂直排列(column):表單場景 \*/

.form {

        display: flex;

        flex-direction: column;

        gap: 15px; /\* 子元素間距,Flex佈局常用 \*/

        width: 300px;

}

.form-item {

        display: flex;

        flex-direction: row; /\* 子元素內部水平排列 \*/

        gap: 10px;

}

一句話總結:水平佈局用row,垂直佈局用column,別搞反主軸方向!

2.2 flex-wrap:控制子元素是否換行

作用:當子元素總寬度 / 高度超過父元素時,是否換行(默認不換行,會壓縮子元素)。

取值與效果

取值 效果 適用場景
nowrap(默認) 不換行,子元素會被壓縮 導航欄(不允許換行)
wrap 換行,第一行在上 卡片網格、商品列表
wrap-reverse 換行,第一行在下 特殊排版(極少用)

常見誤區:做卡片佈局時,忘記加flex-wrap: wrap,導致卡片被壓縮變形!

代碼演示(卡片網格)

.card-container {

        display: flex;

        flex-direction: row;

        flex-wrap: wrap; /\* 關鍵:超出換行 \*/

        gap: 20px;

        padding: 20px;

        background: #f5f5f5;

}

.card {

        width: 200px; /\* 固定寬度 \*/

        height: 300px;

        background: #fff;

        border-radius: 8px;

}

效果:當父元素寬度不足時,卡片自動換行,保持原有尺寸。

2.3 flex-flow:flex-direction + flex-wrap 的簡寫

作用:簡化代碼,將 “方向” 和 “換行” 合併設置,默認值row nowrap

語法flex-flow: <flex-direction> || <flex-wrap>

示例

/\* 等價於 flex-direction: row; flex-wrap: wrap; \*/

.card-container {

        display: flex;

        flex-flow: row wrap;

        gap: 20px;

}

2.4 justify-content:主軸上的對齊方式

作用:控制子元素在主軸方向上的對齊方式(水平或垂直,取決於flex-direction)。

取值與效果(以主軸為水平為例)

取值 效果 適用場景
flex-start(默認) 靠主軸起點對齊(左對齊) 普通列表
flex-end 靠主軸終點對齊(右對齊) 右側操作欄
center 主軸居中對齊 水平居中(如標題)
space-between 兩端對齊,子元素間距相等 導航欄(兩端 logo + 菜單)
space-around 子元素兩側間距相等(中間間距是邊緣 2 倍) 均勻分佈的卡片

代碼演示(space-between 導航欄)

.nav {

        display: flex;

        flex-flow: row nowrap;

        justify-content: space-between; /\* 兩端對齊 \*/

        align-items: center; /\* 交叉軸居中(垂直居中) \*/

        height: 60px;

        padding: 0 20px;

        background: #fff;

}

.nav-logo {

        width: 100px;

}

.nav-menu {

        display: flex;

        gap: 20px;

}

效果:logo 在左,菜單在右,垂直居中對齊。

2.5 align-items:交叉軸上的單行對齊

作用:控制子元素在交叉軸方向上的對齊方式,僅對 “單行子元素” 生效(多行用align-content)。

取值與效果(以交叉軸為垂直為例)

取值 效果 適用場景
stretch(默認) 子元素高度佔滿父元素(需子元素無固定高度) 卡片等高佈局
flex-start 靠交叉軸起點對齊(上對齊) 頂部對齊的列表
flex-end 靠交叉軸終點對齊(下對齊) 底部對齊的操作欄
center 交叉軸居中對齊(垂直居中) 水平垂直居中(如彈窗)
baseline 按子元素文字基線對齊 文字與圖標對齊

常見場景:水平垂直居中(面試高頻):

/\* 父元素:主軸水平,交叉軸垂直 \*/

.container {

        display: flex;

        justify-content: center; /\* 主軸(水平)居中 \*/

        align-items: center; /\* 交叉軸(垂直)居中 \*/

        width: 500px;

        height: 300px;

        background: #f5f5f5;

}

.child {

        width: 100px;

        height: 100px;

        background: #42b983;

}

效果:childcontainer中完全居中,無需定位!

2.6 align-content:交叉軸上的多行對齊

作用:控制 “多行子元素” 在交叉軸上的對齊方式,單行子元素時無效(這是與align-items的核心區別)。

取值與效果(以交叉軸為垂直為例)

取值 效果 適用場景
stretch(默認) 多行高度佔滿父元素 多行卡片等高
flex-start 靠交叉軸起點對齊(上對齊) 多行列表頂部對齊
flex-end 靠交叉軸終點對齊(下對齊) 多行列表底部對齊
center 交叉軸居中對齊 多行內容整體居中
space-between 兩端對齊,行間距相等 均勻分佈的多行卡片
space-around 每行兩側間距相等 寬鬆的多行佈局

代碼演示(space-between 多行卡片)

.card-container {

        display: flex;

        flex-flow: row wrap;

        align-content: space-between; /\* 多行垂直兩端對齊 \*/

        width: 640px;

        height: 600px; /\* 父元素固定高度,才有多行對齊效果 \*/

        gap: 20px;

        padding: 20px;

        background: #f5f5f5;

}

.card {

        width: 200px;

        height: 250px;

        background: #fff;

}

效果:兩行卡片分別靠頂部和底部對齊,中間間距自動分配。

align-items vs align-content 區別

  • align-items:作用於 “單個子元素”,控制每行子元素的對齊;
  • align-content:作用於 “所有行”,控制多行整體的對齊(單行無效)。

三、子元素的 6 個核心屬性:控制自身表現

子元素的屬性用於 “個性化調整”,比如改變排列順序、控制放大縮小、單獨對齊,解決 “特殊子元素” 的需求。

3.1 order:改變子元素的排列順序

作用:通過數值控制子元素的排列優先級,數值越小越靠前(默認 0)。

特點:無需修改 HTML 結構,僅通過 CSS 調整順序,適合動態佈局。

代碼演示(置頂通知)

.list {

        display: flex;

        flex-direction: column;

        gap: 10px;

        padding: 20px;

}

.list-item {

        padding: 10px;

        background: #fff;

}

/\* 通知項置頂(order=-1,比默認0小) \*/

.notice {

        order: -1;

        background: #fff3cd;

        border: 1px solid #ffeeba;

}

效果:notice項會排在所有默認list-item前面。

3.2 flex-grow:控制子元素的放大比例

作用:當父元素有 “剩餘空間” 時,子元素的放大比例(默認 0,即不放大)。

規則

  • 所有子元素的flex-grow總和為 1 時,按比例分配剩餘空間;
  • 若一個子元素flex-grow:2,其他為 1,則它佔的剩餘空間是其他的 2 倍。

代碼演示(三欄佈局:中間自適應)

.layout {

        display: flex;

        width: 100%;

        height: 500px;

        gap: 20px;

}

/\* 左右欄固定寬度,不放大 \*/

.sidebar-left, .sidebar-right {

        width: 200px;

        flex-grow: 0; /\* 默認0,可省略 \*/

        background: #fff;

}

/\* 中間欄自適應放大(佔滿剩餘空間) \*/

.main {

        flex-grow: 1; /\* 剩餘空間全給中間 \*/

        background: #fff;

}

效果:左右欄固定 200px,中間欄隨父元素寬度變化自適應。

3.3 flex-shrink:控制子元素的縮小比例

作用:當父元素 “空間不足” 時,子元素的縮小比例(默認 1,即會縮小)。

規則

  • flex-shrink:0:子元素不縮小,會保持原尺寸(可能溢出父元素);
  • 所有子元素flex-shrink:1:空間不足時等比例縮小。

常見場景(不縮小的圖片)

.card {

        display: flex;

        gap: 10px;

        padding: 10px;

        background: #fff;

        width: 300px; /\* 父元素固定寬度 \*/

}

/\* 圖片不縮小(flex-shrink:0) \*/

.card-img {

        width: 100px;

        height: 100px;

        flex-shrink: 0; /\* 關鍵:防止圖片被壓縮變形 \*/

        object-fit: cover;

}

.card-content {

        flex-grow: 1; /\* 內容區放大,佔滿剩餘空間 \*/

        overflow: hidden; /\* 內容溢出時隱藏 \*/

}

效果:即使父元素寬度不足,圖片仍保持 100px,內容區會壓縮文字(或滾動)。

3.4 flex-basis:定義子元素的基準尺寸

作用:在分配剩餘空間前,子元素在主軸上的 “基準尺寸”(默認 auto,即子元素原尺寸)。

與 width/height 的區別

  • flex-basis優先級高於width/height(當主軸為水平時,flex-basis替代width);
  • flex-basis: 0%,則子元素的基準尺寸為 0,放大時忽略原寬度;
  • flex-basis: auto,則子元素的基準尺寸為原寬度,放大時保留原寬度。

代碼演示(flex-basis: 0% vs auto)

.parent {

        display: flex;

        width: 500px;

        gap: 10px;

        padding: 20px;

        background: #f5f5f5;

}

/\* flex-basis: 0%,忽略width,按比例放大 \*/

.item-0 {

        width: 100px;

        flex-basis: 0%;

        flex-grow: 1;

        background: #42b983;

}

/\* flex-basis: auto,保留width,再分配剩餘空間 \*/

.item-auto {

        width: 100px;

        flex-basis: auto;

        flex-grow: 1;

        background: #ff4757;

}

效果:

  • item-0:最終寬度 = 剩餘空間 / 2(忽略 100px);
  • item-auto:最終寬度 = 100px + 剩餘空間 / 2(保留 100px)。

3.5 flex:flex-grow + flex-shrink + flex-basis 的簡寫

作用:簡化代碼,是子元素最常用的屬性,默認值0 1 auto

常用快捷值及含義

快捷值 等價於 效果 適用場景
flex: 0 flex: 0 1 0% 不放大,可縮小,基準尺寸 0 固定尺寸元素(如圖標)
flex: 1 flex: 1 1 0% 放大,可縮小,基準尺寸 0 自適應元素(如中間欄)
flex: auto flex: 1 1 auto 放大,可縮小,基準尺寸 auto 保留原尺寸的自適應元素
flex: none flex: 0 0 auto 不放大,不縮小,基準尺寸 auto 完全固定尺寸元素

核心區別:flex:1 vs flex:auto(面試高頻):

  • flex:1flex-basis:0%,忽略子元素原寬度,按比例分配剩餘空間;
  • flex:autoflex-basis:auto,保留子元素原寬度,再分配剩餘空間。

代碼演示(區別對比)

.parent {

        display: flex;

        width: 500px;

        gap: 10px;

        padding: 20px;

        background: #f5f5f5;

}

/\* flex:1 忽略width \*/

.item-1 {

        width: 200px;

        flex: 1;

        background: #42b983;

}

/\* flex:auto 保留width \*/

.item-auto {

        width: 200px;

        flex: auto;

        background: #ff4757;

}

效果:

  • item-1:最終寬度 = (500 - 10)/2 = 245px(忽略 200px);
  • item-auto:最終寬度 = 200px + (500 - 200*2 -10)/2 = 245px?不,實際是:父元素總寬度 500,減去 gap10,剩餘 490;item-auto基準 200,item-1基準 0,總基準 200;剩餘空間 490-200=290;flex-grow都是 1,各分 145;所以item-auto最終 200+145=345,item-10+145=145。

    (注:實際計算需考慮 gap,這裏重點是 “flex:1 忽略 width,flex:auto 保留 width”)

3.6 align-self:單獨設置子元素的交叉軸對齊

作用:覆蓋父元素的align-items屬性,為單個子元素設置特殊的交叉軸對齊方式(默認 auto,即繼承父元素)。

取值:與align-items一致(flex-start、flex-end、center、baseline、stretch)。

代碼演示(特殊對齊的按鈕)

.form {

        display: flex;

        flex-direction: row;

        align-items: center; /\* 父元素默認居中對齊 \*/

        gap: 10px;

        padding: 20px;

        background: #f5f5f5;

}

.form-input {

        flex-grow: 1;

        padding: 8px;

        border: 1px solid #ddd;

}

/\* 按鈕單獨向下對齊(覆蓋父元素的center) \*/

.form-btn {

        padding: 8px 16px;

        background: #42b983;

        color: #fff;

        border: none;

        align-self: flex-end;

}

效果:輸入框垂直居中,按鈕靠底部對齊,滿足特殊佈局需求。

四、Flex 佈局避坑指南:解決 90% 常見錯誤

掌握屬性後,仍可能踩坑,這 3 個誤區最容易犯,一定要避開!

4.1 誤區 1:主軸方向設為 column 後,對齊屬性用反

錯誤場景:父元素flex-direction: column(主軸垂直),想讓子元素水平居中,卻用了justify-content: center(主軸對齊,此時控制垂直方向),導致沒效果。

正確做法:主軸垂直時,justify-content控制垂直方向,align-items控制水平方向。

/\* 錯誤:想水平居中,卻用了justify-content \*/

.parent {

        display: flex;

        flex-direction: column;

        justify-content: center; /\* 此時控制垂直居中,不是水平 \*/

}

/\* 正確:水平居中用align-items \*/

.parent {

        display: flex;

        flex-direction: column;

        align-items: center; /\* 水平居中 \*/

        justify-content: center; /\* 垂直居中(可選) \*/

}

4.2 誤區 2:用 align-content 控制單行子元素

錯誤場景:子元素只有一行,卻用align-content: center想讓子元素垂直居中,結果沒效果。

原因align-content僅對多行子元素生效,單行需用align-items

正確做法

/\* 錯誤:單行用align-content \*/

.parent {

        display: flex;

        align-content: center; /\* 單行無效 \*/

}

/\* 正確:單行用align-items \*/

.parent {

        display: flex;

        align-items: center; /\* 單行垂直居中 \*/

}

4.3 誤區 3:flex-shrink:0 導致子元素溢出

錯誤場景:子元素設置flex-shrink:0(不縮小),且寬度固定,當父元素寬度不足時,子元素溢出父元素。

解決方法:配合min-width: 0overflow: hidden,讓子元素內容可壓縮或滾動。

/\* 錯誤:子元素溢出 \*/

.parent {

        display: flex;

        width: 200px; /\* 父元素寬度不足 \*/

}

.child {

        width: 300px;

        flex-shrink: 0; /\* 不縮小,導致溢出 \*/

}

/\* 正確:內容溢出時滾動 \*/

.child {

        width: 300px;

        flex-shrink: 0;

        overflow-x: auto; /\* 橫向滾動 \*/

}

五、Flex 佈局實戰案例:從理論到應用

結合實際需求,用 Flex 實現 4 種常見佈局,鞏固所學知識。

5.1 案例 1:水平垂直居中(彈窗內容區)

.modal {

        position: fixed;

        top: 0;

        left: 0;

        width: 100%;

        height: 100%;

        background: rgba(0,0,0,0.5);

        /\* 父元素:水平垂直居中 \*/

        display: flex;

        justify-content: center;

        align-items: center;

}

.modal-content {

        width: 500px;

        padding: 30px;

        background: #fff;

        border-radius: 8px;

}

5.2 案例 2:三欄佈局(後台管理系統)

.admin-layout {

        display: flex;

        width: 100%;

        height: 100vh;

}

/\* 左側邊欄:固定寬度,不放大 \*/

.sidebar {

        width: 240px;

        flex-shrink: 0;

        background: #2c3e50;

        color: #fff;

}

/\* 中間內容區:自適應放大 \*/

.content {

        flex-grow: 1;

        padding: 20px;

        background: #ecf0f1;

        overflow-y: auto;

}

/\* 右側工具欄:固定寬度,不放大 \*/

.toolbar {

        width: 200px;

        flex-shrink: 0;

        background: #fff;

        padding: 20px;

}

5.3 案例 3:卡片網格(商品列表)

.product-list {

        display: flex;

        flex-flow: row wrap;

        gap: 20px;

        padding: 20px;

        background: #f5f5f5;

        /\* 讓卡片在父元素縮小時,自動調整數量 \*/

        justify-content: flex-start;

        align-content: flex-start;

}

.product-card {

        width: calc((100% - 40px) / 3); /\* 一行3個,減去2個gap \*/

        flex-shrink: 0; /\* 不縮小,保持寬度 \*/

        height: 300px;

        background: #fff;

        border-radius: 8px;

        overflow: hidden;

}

/\* 響應式:屏幕小於768px時,一行2個 \*/

@media (max-width: 768px) {

        .product-card {

          width: calc((100% - 20px) / 2);

        }

}

5.4 案例 4:導航欄(兩端對齊 + 溢出滾動)

.nav {

        display: flex;

        flex-flow: row nowrap;

        justify-content: space-between;

        align-items: center;

        height: 60px;

        padding: 0 20px;

        background: #fff;

        border-bottom: 1px solid #eee;

}

/\* 左側logo:固定寬度 \*/

.nav-logo {

        width: 120px;

        flex-shrink: 0;

}

/\* 中間菜單:溢出時滾動 \*/

.nav-menu {

        display: flex;

        gap: 20px;

        margin: 0 20px;

        overflow-x: auto;

        /\* 隱藏滾動條,保留滾動功能 \*/

        scrollbar-width: none;

        -ms-overflow-style: none;

}

.nav-menu::-webkit-scrollbar {

        display: none;

}

.nav-menu-item {

        padding: 10px 0;

        white-space: nowrap; /\* 不換行 \*/

}

/\* 右側用户區:固定寬度 \*/

.nav-user {

        width: 100px;

        flex-shrink: 0;

        text-align: right;

}

六、Flex 屬性速查表(收藏備用)

父元素屬性速查表

屬性名 作用 取值 常用場景
flex-direction 決定主軸方向(子元素排列方向) row/row-reverse/column/column-reverse 水平 / 垂直佈局
flex-wrap 控制子元素是否換行 nowrap/wrap/wrap-reverse 卡片網格、列表
flex-flow 簡寫(direction+wrap)
justify-content 主軸對齊方式 flex-start/flex-end/center/space-between/space-around 水平 / 垂直居中、兩端對齊
align-items 交叉軸單行對齊 stretch/flex-start/flex-end/center/baseline 垂直居中、等高佈局
align-content 交叉軸多行對齊 stretch/flex-start/flex-end/center/space-between/space-around 多行卡片對齊

子元素屬性速查表

屬性名 作用 取值 常用場景
order 改變排列順序 (默認 0) 置頂 / 置底元素
flex-grow 放大比例 (默認 0) 自適應元素(中間欄)
flex-shrink 縮小比例 (默認 1) 固定尺寸元素(圖片)
flex-basis 基準尺寸 /auto(默認 auto) 自定義基準尺寸
flex 簡寫(grow+shrink+basis) 0/1/auto/none 自適應、固定尺寸元素
align-self 單獨交叉軸對齊 auto/flex-start/flex-end/center/baseline/stretch 特殊對齊元素

結語:Flex 佈局的核心思想

Flex 佈局的本質是 “彈性”—— 通過主軸與交叉軸的靈活定義,實現 “按需分配空間” 和 “精準對齊”。掌握它的關鍵不是死記屬性,而是:

  1. 先確定主軸方向(flex-direction);
  2. 再用父元素屬性控制整體佈局;
  3. 最後用子元素屬性調整特殊需求。

多動手實現幾個實戰案例,遇到問題查速查表,很快就能熟練掌握。Flex 佈局是前端開發的 “瑞士軍刀”,用好它,能大幅提升佈局效率,告別 “浮動塌陷” 和 “定位混亂” 的煩惱!總而言之,一鍵點贊、評論、喜歡收藏吧!這對我很重要!

user avatar toopoo 头像 nihaojob 头像 qingzhan 头像 razyliang 头像 inslog 头像 u_17443142 头像 shuirong1997 头像 guixiangyyds 头像 ccVue 头像 kitty-38 头像 xw-01 头像 abc-x 头像
点赞 74 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.