一、前言
最近在項目裏遇到了一個 Flex 佈局的問題,才發現自己對它的理解還是停留在淺顯的水平,遇到一些特殊情況就不知道如何處理。於是找了些資料深入學習一下,然後將我的學習心得總結成這篇文章。
二、問題還原
先講講我遇到的問題。我希望實現一個左中右三列的佈局,其中左右部分固定寬度,中間部分自適應:
實現起來很簡單,代碼如下:
<div class="container">
<div class="left">left</div>
<div class="middle">
middle
</div>
<div class="right">right</div>
</div>
.container {
display: flex;
width: auto;
height: 300px;
background: grey;
}
.left {
flex-basis: 200px;
background: linear-gradient(to bottom right, green, white);
}
.middle {
flex: 1;
background: linear-gradient(to bottom right, yellow, white);
}
.right {
flex-basis: 300px;
background: linear-gradient(to bottom right, purple, white);
}
到此爲止一切都很美好。但遇到中間部分內容很長的時候,UI 就變形了:
爲了固定住左右部分的寬度,需要給 left 和 right 加上flex-shrink: 0
。但加上後容器的寬度就被撐開了,頁面底部出現了滾動條:
而我期望的效果是滾動條出現在中間部分,整個頁面不能滾動。解決方法是給 middle 加上overflow: scroll
:
此時的完整代碼如下:
<div class="container">
<div class="left">left</div>
<div class="middle">
middle
<!-- 寬度爲800px的內容-->
<div class="long">long</div>
</div>
<div class="right">right</div>
</div>
.container {
display: flex;
width: auto;
height: 300px;
background: grey;
}
.left {
flex-basis: 200px;
flex-shrink: 0;
background: linear-gradient(to bottom right, green, white);
}
.middle {
flex: 1;
overflow: scroll;
background: linear-gradient(to bottom right, yellow, white);
}
.right {
flex-basis: 300px;
flex-shrink: 0;
background: linear-gradient(to bottom right, purple, white);
}
.long {
width: 800px;
}
完整的 codepen
在這裏
實戰經驗到此結束,下面我們再深入學習涉及到的知識點。
三、知識點
先來講講上面用到的屬性flex: 1
。它其實是一個縮寫,等價於flex: 1 1 0
,也就是
flex-grow : 1;
flex-shrink : 1;
flex-basis : 0;
- flex-grow 表示當有剩餘空間的時候,分配給項目的比例
- flex-shrink 表示空間不足的時候,項目縮小的比例
- flex-basis 表示分配空間之前,項目佔據主軸的空間
下面來講講 flex 空間分配的步驟。
flex-grow(默認值 0)
假設有一個寬度爲 800 的容器,裏面有 3 個項目,寬度分別是 100,200,300:
<div class="container">
<div class="left">left</div>
<div class="middle">middle</div>
<div class="right">right</div>
</div>
.container {
display: flex;
width: 800px;
height: 300px;
background: grey;
}
.left {
flex-basis: 100px;
background: linear-gradient(to bottom right, green, white);
}
.middle {
flex-basis: 200px;
background: linear-gradient(to bottom right, yellow, white);
}
.right {
flex-basis: 300px;
background: linear-gradient(to bottom right, purple, white);
}
效果如下:
這時候就出現了多餘的 200 的空間(灰色部分)。這時候如果我們對左中右分別設置flex-grow
爲 2,1,1,各個項目的計算邏輯如下:
- 首先將多餘空間 200 除以 4(2 + 1 + 1),等於 50
- left = 100 + 2 x 50 = 200
- middle = 200 + 1 x 50 = 250
- right = 300 + 1 x 50 = 350
flex-shrink(默認值 1)
假設父容器寬度調整爲 550,裏面依然是 3 個項目,寬度分別是 100,200,300,這時候空間就不夠用溢出了。首先要理解清楚,當我們定義一個固定寬度容器爲flex
的時候,flex
會盡其所能不去改變容器的寬度,而是壓縮項目的寬度。這時我們對左中右分別設置flex-shrink
爲 1,2,3,計算邏輯如下:
- 溢出空間 = 100 + 200 + 300 - 550 = 50
- 總權重 = 1 x 100 + 2 x 200 + 3 x 300 = 1400
- left = 100 - (50 x 1 x 100 / 1400) = 96.42
- middle = 200 - (50 x 2 x 200 / 1400) = 185.72
- right = 300 - (50 x 3 x 300 / 1400) = 267.86
如果我們不想項目被壓縮,就必須將flex-shrink
設爲 0。還是用上面的例子,當左中右的flex-shrink
都爲 0 的時候,就會衝破寬度限制,container的寬度將會從 550 變爲 600。
codepen
在這裏
flex-basis(默認值 auto)
flex-basis
指定項目佔據主軸的空間,如果不設置,則等於內容本身的空間:
四、總結
本文從問題出發,講解了Flex
佈局在實戰中的應用,並深入到flex-grow
,flex-shrink
和flex-basis
的細節,描述了項目空間在填充和溢出情況下的計算方式,希望對你有所幫助。